Mercurial > hg > graal-jvmci-8
comparison test/runtime/testlibrary/GeneratedClassLoader.java @ 10344:699d9df07e59
8009576: Test returns ClassNotFoundException
Summary: Small classpath fix and move tests into open
Reviewed-by: mgerdin, zgu
author | ctornqvi |
---|---|
date | Thu, 23 May 2013 17:39:32 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
10343:6bd680e9ea35 | 10344:699d9df07e59 |
---|---|
1 /* | |
2 * Copyright (c) 2013, 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 import java.io.DataInputStream; | |
25 import java.io.File; | |
26 import java.io.FileInputStream; | |
27 import java.io.FileWriter; | |
28 import java.io.IOException; | |
29 import java.io.PrintWriter; | |
30 import javax.tools.JavaCompiler; | |
31 import javax.tools.ToolProvider; | |
32 | |
33 /** | |
34 * A class loader that generates new classes. | |
35 * The generated classes are made by first emitting java sources with nested | |
36 * static classes, these are then compiled and the class files are read back. | |
37 * Some efforts are made to make the class instances unique and of not insignificant | |
38 * size. | |
39 */ | |
40 public class GeneratedClassLoader extends ClassLoader { | |
41 /** | |
42 * Holds a pair of class bytecodes and class name (for use with defineClass). | |
43 */ | |
44 private static class GeneratedClass { | |
45 public byte[] bytes; | |
46 public String name; | |
47 public GeneratedClass(byte[] bytes, String name) { | |
48 this.bytes = bytes; this.name = name; | |
49 } | |
50 } | |
51 | |
52 /** | |
53 * Used to uniquely name every class generated. | |
54 */ | |
55 private static int count = 0; | |
56 /** | |
57 * Used to enable/disable keeping the class files and java sources for | |
58 * the generated classes. | |
59 */ | |
60 private static boolean deleteFiles = Boolean.parseBoolean( | |
61 System.getProperty("GeneratedClassLoader.deleteFiles", "true")); | |
62 | |
63 private static String bigstr = | |
64 "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " | |
65 + "In facilisis scelerisque vehicula. Donec congue nisi a " | |
66 + "leo posuere placerat lobortis felis ultrices. Pellentesque " | |
67 + "habitant morbi tristique senectus et netus et malesuada " | |
68 + "fames ac turpis egestas. Nam tristique velit at felis " | |
69 + "iaculis at tempor sem vestibulum. Sed adipiscing lectus " | |
70 + "non mi molestie sagittis. Morbi eu purus urna. Nam tempor " | |
71 + "tristique massa eget semper. Mauris cursus, nulla et ornare " | |
72 + "vehicula, leo dolor scelerisque metus, sit amet rutrum erat " | |
73 + "sapien quis dui. Nullam eleifend risus et velit accumsan sed " | |
74 + "suscipit felis pulvinar. Nullam faucibus suscipit gravida. " | |
75 + "Pellentesque habitant morbi tristique senectus et netus et " | |
76 + "malesuada fames ac turpis egestas. Nullam ut massa augue, " | |
77 + "nec viverra mauris."; | |
78 | |
79 private static int getNextCount() { | |
80 return count++; | |
81 } | |
82 | |
83 ////// end statics | |
84 | |
85 private JavaCompiler javac; | |
86 private String nameBase; | |
87 | |
88 public GeneratedClassLoader() { | |
89 javac = ToolProvider.getSystemJavaCompiler(); | |
90 nameBase = "TestSimpleClass"; | |
91 } | |
92 | |
93 private long getBigValue(int which) { | |
94 // > 65536 is too large to encode in the bytecode | |
95 // so this will force us to emit a constant pool entry for this int | |
96 return (long)which + 65537; | |
97 } | |
98 | |
99 private String getBigString(int which) { | |
100 return bigstr + which; | |
101 } | |
102 | |
103 private String getClassName(int count) { | |
104 return nameBase + count; | |
105 } | |
106 | |
107 private String generateSource(int count, int sizeFactor, int numClasses) { | |
108 StringBuilder sb = new StringBuilder(); | |
109 sb.append("public class ").append(getClassName(count)).append("{\n"); | |
110 for (int j = 0; j < numClasses; ++j) { | |
111 sb.append("public static class ") | |
112 .append("Class") | |
113 .append(j) | |
114 .append("{\n"); | |
115 for (int i = 0; i < sizeFactor; ++i) { | |
116 int value = i; | |
117 sb.append("private long field") | |
118 .append(i).append(" = ") | |
119 .append(getBigValue(value++)) | |
120 .append(";\n"); | |
121 sb.append("public long method") | |
122 .append(i) | |
123 .append("() {\n"); | |
124 sb.append("return ") | |
125 .append(getBigValue(value++)) | |
126 .append(";"); | |
127 sb.append("}\n"); | |
128 sb.append("private String str").append(i) | |
129 .append(" = \"") | |
130 .append(getBigString(i)) | |
131 .append("\";"); | |
132 } | |
133 sb.append("\n}"); | |
134 } | |
135 sb.append("\n}"); | |
136 return sb.toString(); | |
137 } | |
138 | |
139 private GeneratedClass[] getGeneratedClass(int sizeFactor, int numClasses) throws IOException { | |
140 int uniqueCount = getNextCount(); | |
141 String src = generateSource(uniqueCount, sizeFactor, numClasses); | |
142 String className = getClassName(uniqueCount); | |
143 File file = new File(className + ".java"); | |
144 try (PrintWriter pw = new PrintWriter(new FileWriter(file))) { | |
145 pw.append(src); | |
146 pw.flush(); | |
147 } | |
148 int exitcode = javac.run(null, null, null, file.getCanonicalPath()); | |
149 if (exitcode != 0) { | |
150 throw new RuntimeException("javac failure when compiling: " + | |
151 file.getCanonicalPath()); | |
152 } else { | |
153 if (deleteFiles) { | |
154 file.delete(); | |
155 } | |
156 } | |
157 GeneratedClass[] gc = new GeneratedClass[numClasses]; | |
158 for (int i = 0; i < numClasses; ++i) { | |
159 String name = className + "$" + "Class" + i; | |
160 File classFile = new File(name + ".class"); | |
161 byte[] bytes; | |
162 try (DataInputStream dis = new DataInputStream(new FileInputStream(classFile))) { | |
163 bytes = new byte[dis.available()]; | |
164 dis.readFully(bytes); | |
165 } | |
166 if (deleteFiles) { | |
167 classFile.delete(); | |
168 } | |
169 gc[i] = new GeneratedClass(bytes, name); | |
170 } | |
171 if (deleteFiles) { | |
172 new File(className + ".class").delete(); | |
173 } | |
174 return gc; | |
175 } | |
176 | |
177 /** | |
178 * Generate a single class, compile it and load it. | |
179 * @param sizeFactor Fuzzy measure of how large the class should be. | |
180 * @return the Class instance. | |
181 * @throws IOException | |
182 */ | |
183 public Class<?> generateClass(int sizeFactor) throws IOException { | |
184 return getGeneratedClasses(sizeFactor, 1)[0]; | |
185 } | |
186 | |
187 /** | |
188 * Generate several classes, compile and load them. | |
189 * @param sizeFactor Fuzzy measure of how large each class should be. | |
190 * @param numClasses The number of classes to create | |
191 * @return an array of the Class instances. | |
192 * @throws IOException | |
193 */ | |
194 public Class<?>[] getGeneratedClasses(int sizeFactor, int numClasses) throws IOException { | |
195 GeneratedClass[] gc = getGeneratedClass(sizeFactor, numClasses); | |
196 Class<?>[] classes = new Class[numClasses]; | |
197 for (int i = 0; i < numClasses; ++i) { | |
198 classes[i] = defineClass(gc[i].name, gc[i].bytes, 0 , gc[i].bytes.length); | |
199 } | |
200 return classes; | |
201 } | |
202 } |