1 /* 2 * Copyright (c) 2018, 2021, 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 */ 23 24 /** 25 * @test 26 * @bug 8193717 27 * @summary Check that code with a lot named imports can compile. 28 * @library /tools/lib 29 * @modules jdk.jdeps/com.sun.tools.classfile 30 * jdk.compiler/com.sun.tools.javac.api 31 * jdk.compiler/com.sun.tools.javac.main 32 * jdk.jdeps/com.sun.tools.javap 33 * @build toolbox.ToolBox toolbox.JavapTask 34 * @run main T8193717 35 */ 36 37 import java.io.ByteArrayInputStream; 38 import java.io.ByteArrayOutputStream; 39 import java.io.IOException; 40 import java.io.InputStream; 41 import java.net.URI; 42 import java.net.URISyntaxException; 43 import java.nio.file.Paths; 44 import java.util.ArrayList; 45 import java.util.List; 46 import java.util.Set; 47 48 import javax.tools.ForwardingJavaFileManager; 49 import javax.tools.JavaCompiler; 50 import javax.tools.JavaFileManager; 51 import javax.tools.JavaFileObject; 52 import javax.tools.JavaFileObject.Kind; 53 import javax.tools.SimpleJavaFileObject; 54 import javax.tools.StandardJavaFileManager; 55 import javax.tools.StandardLocation; 56 import javax.tools.ToolProvider; 57 58 import com.sun.tools.classfile.AccessFlags; 59 import com.sun.tools.classfile.Attribute; 60 import com.sun.tools.classfile.Attributes; 61 import com.sun.tools.classfile.ClassFile; 62 import com.sun.tools.classfile.ClassWriter; 63 import com.sun.tools.classfile.ConstantPool; 64 import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info; 65 import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info; 66 import com.sun.tools.classfile.ConstantPool.CPInfo; 67 import com.sun.tools.classfile.Field; 68 import com.sun.tools.classfile.Method; 69 70 import toolbox.JavacTask; 71 import toolbox.ToolBox; 72 73 public class T8193717 { main(String... args)74 public static void main(String... args) throws IOException { 75 new T8193717().run(); 76 } 77 78 private static final int CLASSES = 50000; 79 run()80 private void run() throws IOException { 81 StringBuilder imports = new StringBuilder(); 82 StringBuilder use = new StringBuilder(); 83 84 for (int c = 0; c < CLASSES; c++) { 85 String simpleName = getSimpleName(c); 86 String pack = "p"; 87 imports.append("import " + pack + "." + simpleName + ";\n"); 88 use.append(simpleName + " " + simpleName + ";\n"); 89 } 90 String source = imports.toString() + "public class T {\n" + use.toString() + "}"; 91 ToolBox tb = new ToolBox(); 92 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 93 94 try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) { 95 fm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT, List.of(Paths.get("."))); 96 new JavacTask(tb).sources(source) 97 .options("-XDshould-stop.ifError=ATTR", 98 "-XDshould-stop.ifNoError=ATTR") //the source is too big for a classfile 99 .fileManager(new TestJFM(fm)) 100 .run(); 101 } 102 } 103 getSimpleName(int c)104 private static String getSimpleName(int c) { 105 return "T" + String.format("%0" + (int) Math.ceil(Math.log10(CLASSES)) + "d", c); 106 } 107 generateClassFile(String name)108 private byte[] generateClassFile(String name) throws IOException { 109 ConstantPool cp = new ConstantPool(new CPInfo[] { 110 new CONSTANT_Utf8_info(""), //0 111 new CONSTANT_Utf8_info(name.replace(".", "/")), //1 112 new CONSTANT_Class_info(null, 1), //2 113 new CONSTANT_Utf8_info("java/lang/Object"), //3 114 new CONSTANT_Class_info(null, 3), //4 115 }); 116 ClassFile cf = new ClassFile(0xCAFEBABE, 117 0, 118 51, 119 cp, 120 new AccessFlags(AccessFlags.ACC_ABSTRACT | 121 AccessFlags.ACC_INTERFACE | 122 AccessFlags.ACC_PUBLIC), 123 2, 124 4, 125 new int[0], 126 new Field[0], 127 new Method[0], 128 new Attributes(cp, new Attribute[0])); 129 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 130 new ClassWriter().write(cf, baos); 131 return baos.toByteArray(); 132 } 133 134 final class TestJFM extends ForwardingJavaFileManager<JavaFileManager> { 135 TestJFM(JavaFileManager fileManager)136 public TestJFM(JavaFileManager fileManager) { 137 super(fileManager); 138 } 139 140 @Override list(Location location, String packageName, Set<Kind> kinds, boolean recurse)141 public Iterable<JavaFileObject> list(Location location, String packageName, 142 Set<Kind> kinds, boolean recurse) throws IOException { 143 if (location == StandardLocation.CLASS_PATH) { 144 if (packageName.equals("p")) { 145 try { 146 List<JavaFileObject> result = new ArrayList<>(CLASSES); 147 148 for (int c = 0; c < CLASSES; c++) { 149 result.add(new TestJFO("p." + getSimpleName(c))); 150 } 151 152 return result; 153 } catch (URISyntaxException ex) { 154 throw new IllegalStateException(ex); 155 } 156 } 157 } 158 return super.list(location, packageName, kinds, recurse); 159 } 160 161 @Override inferBinaryName(Location location, JavaFileObject file)162 public String inferBinaryName(Location location, JavaFileObject file) { 163 if (file instanceof TestJFO) { 164 return ((TestJFO) file).name; 165 } 166 return super.inferBinaryName(location, file); 167 } 168 169 private class TestJFO extends SimpleJavaFileObject { 170 171 private final String name; 172 TestJFO(String name)173 public TestJFO(String name) throws URISyntaxException { 174 super(new URI("mem://" + name.replace(".", "/") + ".class"), Kind.CLASS); 175 this.name = name; 176 } 177 178 @Override openInputStream()179 public InputStream openInputStream() throws IOException { 180 return new ByteArrayInputStream(generateClassFile(name)); 181 } 182 } 183 184 } 185 } 186