test/tools/javac/lambda/lambdaNaming/TestNonSerializableLambdaNameStability.java

Wed, 16 Sep 2015 10:56:23 +0200

author
jlahoda
date
Wed, 16 Sep 2015 10:56:23 +0200
changeset 2701
6906fc8bc514
permissions
-rw-r--r--

8067422: Lambda method names are unnecessarily unstable
Summary: Lambda method numbers are now assigned per class for non-serializable lambdas.
Reviewed-by: mcimadamore, rfield, vromero

     1 /*
     2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  */
    24 /*
    25  * @test
    26  * @bug 8067422
    27  * @summary Check that the lambda names are not unnecessarily unstable
    28  * @run main TestNonSerializableLambdaNameStability
    29  */
    31 import com.sun.tools.classfile.ClassFile;
    32 import com.sun.tools.classfile.Method;
    34 import java.io.ByteArrayInputStream;
    35 import java.io.ByteArrayOutputStream;
    36 import java.io.IOException;
    37 import java.io.InputStream;
    38 import java.io.OutputStream;
    39 import java.net.URI;
    40 import java.net.URISyntaxException;
    41 import java.util.ArrayList;
    42 import java.util.HashMap;
    43 import java.util.List;
    44 import java.util.Map;
    46 import javax.tools.FileObject;
    47 import javax.tools.ForwardingJavaFileManager;
    48 import javax.tools.JavaCompiler;
    49 import javax.tools.JavaFileManager;
    50 import javax.tools.JavaFileObject;
    51 import javax.tools.JavaFileObject.Kind;
    52 import javax.tools.SimpleJavaFileObject;
    53 import javax.tools.ToolProvider;
    55 public class TestNonSerializableLambdaNameStability {
    57     public static void main(String... args) throws Exception {
    58         new TestNonSerializableLambdaNameStability().run();
    59     }
    61     String lambdaSource = "public class L%d {\n" +
    62                           "    public static class A {\n" +
    63                           "        private Runnable r = () -> { };\n" +
    64                           "    }\n" +
    65                           "    public static class B {\n" +
    66                           "        private Runnable r = () -> { };\n" +
    67                           "    }\n" +
    68                           "    private Runnable r = () -> { };\n" +
    69                           "}\n";
    71     String expectedLambdaMethodName = "lambda$new$0";
    73     void run() throws Exception {
    74         List<JavaFileObject> sources = new ArrayList<>();
    76         for (int i = 0; i < 3; i++) {
    77             sources.add(new SourceJavaFileObject("L" + i, String.format(lambdaSource, i)));
    78         }
    80         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    82         try (MemoryFileManager fm = new MemoryFileManager(compiler.getStandardFileManager(null, null, null))) {
    83             if (!compiler.getTask(null, fm, null, null, null, sources).call()) {
    84                 throw new AssertionError("Compilation failed!");
    85             }
    87             for (String file : fm.name2Content.keySet()) {
    88                 byte[] fileBytes = fm.name2Content.get(file);
    89                 try (InputStream in = new ByteArrayInputStream(fileBytes)) {
    90                     boolean foundLambdaMethod = false;
    91                     ClassFile cf = ClassFile.read(in);
    92                     StringBuilder seenMethods = new StringBuilder();
    93                     String sep = "";
    94                     for (Method m : cf.methods) {
    95                         String methodName = m.getName(cf.constant_pool);
    96                         if (expectedLambdaMethodName.equals(methodName)) {
    97                             foundLambdaMethod = true;
    98                             break;
    99                         }
   100                         seenMethods.append(sep);
   101                         seenMethods.append(methodName);
   102                         sep = ", ";
   103                     }
   105                     if (!foundLambdaMethod) {
   106                         throw new AbstractMethodError("Did not find the lambda method, " +
   107                                                       "found methods: " + seenMethods.toString());
   108                     }
   109                 }
   110             }
   111         }
   112     }
   114     class MemoryFileManager extends ForwardingJavaFileManager<JavaFileManager> {
   116         final Map<String, byte[]> name2Content = new HashMap<>();
   118         public MemoryFileManager(JavaFileManager fileManager) {
   119             super(fileManager);
   120         }
   122         @Override
   123         public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
   124             try {
   125                 return new SimpleJavaFileObject(new URI("mem://" + className.replace('.', '/') + kind.extension), kind) {
   126                     @Override public OutputStream openOutputStream() throws IOException {
   127                         return new ByteArrayOutputStream() {
   128                             @Override public void close() throws IOException {
   129                                 super.close();
   130                                 name2Content.put(className, toByteArray());
   131                             }
   132                         };
   133                     }
   134                 };
   135             } catch (URISyntaxException ex) {
   136                 throw new AssertionError(ex);
   137             }
   138         }
   140     }
   142     class SourceJavaFileObject extends SimpleJavaFileObject {
   144         private final String code;
   146         public SourceJavaFileObject(String name, String code) throws URISyntaxException {
   147             super(new URI("mem:///" + name + ".java"), Kind.SOURCE);
   148             this.code = code;
   149         }
   151         @Override
   152         public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
   153             return code;
   154         }
   156     }
   157 }

mercurial