22
22
*
23
23
*/
24
24
25
- import javax .tools .*;
26
- import java .io .*;
25
+ import java .lang .invoke .MethodHandles ;
26
+ import java .io .ByteArrayOutputStream ;
27
+ import java .io .IOException ;
27
28
import java .net .URI ;
28
- import java .util .*;
29
+ import java .util .ArrayList ;
30
+ import java .util .Collection ;
31
+ import java .util .HashMap ;
32
+ import java .util .List ;
33
+ import java .util .Map ;
34
+ import java .util .concurrent .Callable ;
35
+ import javax .tools .Diagnostic ;
36
+ import javax .tools .DiagnosticCollector ;
37
+ import javax .tools .FileObject ;
38
+ import javax .tools .ForwardingJavaFileManager ;
39
+ import javax .tools .JavaCompiler ;
40
+ import javax .tools .JavaFileManager ;
41
+ import javax .tools .JavaFileObject ;
42
+ import javax .tools .SimpleJavaFileObject ;
43
+ import javax .tools .ToolProvider ;
29
44
30
45
/**
31
46
* This program tries to compile a large number of classes that exercise a fair amount of
@@ -57,7 +72,7 @@ public ClassFile getJavaFileForOutput(Location location, String name, JavaFileOb
57
72
classesMap .put (name , classFile );
58
73
return classFile ;
59
74
}
60
- public Map <String , byte []> getByteCode () {
75
+ public Map <String , byte []> getCompiledClasses () {
61
76
Map <String , byte []> result = new HashMap <>();
62
77
for (Map .Entry <String , ClassFile > entry : classesMap .entrySet ()) {
63
78
result .put (entry .getKey (), entry .getValue ().toByteArray ());
@@ -78,19 +93,19 @@ public CharSequence getCharContent(boolean ignore) {
78
93
}
79
94
}
80
95
81
- public Object compile (int count ) {
96
+ public Map < String , byte []> compile () {
82
97
JavaCompiler compiler = ToolProvider .getSystemJavaCompiler ();
83
98
DiagnosticCollector <JavaFileObject > ds = new DiagnosticCollector <>();
84
- Collection <SourceFile > sourceFiles = sources . subList ( 0 , count ) ;
99
+ Collection <SourceFile > sourceFiles = sources ;
85
100
86
101
try (FileManager fileManager = new FileManager (compiler .getStandardFileManager (ds , null , null ))) {
87
102
JavaCompiler .CompilationTask task = compiler .getTask (null , fileManager , null , null , null , sourceFiles );
88
103
if (task .call ()) {
89
- return fileManager .getByteCode ();
104
+ return fileManager .getCompiledClasses ();
90
105
} else {
91
106
for (Diagnostic <? extends JavaFileObject > d : ds .getDiagnostics ()) {
92
- System .out .format ("Line: %d, %s in %s" , d .getLineNumber (), d .getMessage (null ), d .getSource ().getName ());
93
- }
107
+ System .out .format ("Line: %d, %s in %s" , d .getLineNumber (), d .getMessage (null ), d .getSource ().getName ());
108
+ }
94
109
throw new InternalError ("compilation failure" );
95
110
}
96
111
} catch (IOException e ) {
@@ -161,34 +176,52 @@ public Point(int x) {
161
176
}
162
177
""" ;
163
178
164
- List <SourceFile > generate (int count ) {
165
- ArrayList <SourceFile > sources = new ArrayList <>(count );
179
+ String sanitySource = """
180
+ public class Sanity implements java.util.concurrent.Callable<String> {
181
+ public String call() {
182
+ return "this is a test";
183
+ }
184
+ }
185
+ """ ;
186
+
187
+ void setup (int count ) {
188
+ sources = new ArrayList <>(count );
166
189
for (int i = 0 ; i < count ; i ++) {
167
190
String source = imports + "public class Test" + i + " {" + testClassBody + "}" ;
168
191
sources .add (new SourceFile ("Test" + i , source ));
169
192
}
170
- return sources ;
193
+
194
+ sources .add (new SourceFile ("Sanity" , sanitySource ));
171
195
}
172
196
173
- public void setup () {
174
- sources = generate (10_000 );
197
+ @ SuppressWarnings ("unchecked" )
198
+ static void validate (byte [] sanityClassFile ) throws Throwable {
199
+ MethodHandles .Lookup lookup = MethodHandles .lookup ();
200
+ Class <?> cls = lookup .defineClass (sanityClassFile );
201
+ Callable <String > obj = (Callable <String >)cls .getDeclaredConstructor ().newInstance ();
202
+ String s = obj .call ();
203
+ if (!s .equals ("this is a test" )) {
204
+ throw new RuntimeException ("Expected \" this is a test\" , but got \" " + s + "\" " );
205
+ }
175
206
}
176
207
177
208
public static void main (String args []) throws Throwable {
178
209
long started = System .currentTimeMillis ();
179
210
JavacBenchApp bench = new JavacBenchApp ();
180
- bench . setup ();
211
+
181
212
int count = 0 ;
182
213
if (args .length > 0 ) {
183
214
count = Integer .parseInt (args [0 ]);
184
- if (count > 0 ) {
185
- bench .compile (count );
215
+ if (count >= 0 ) {
216
+ bench .setup (count );
217
+ Map <String , byte []> allClasses = bench .compile ();
218
+ validate (allClasses .get ("Sanity" ));
186
219
}
187
220
}
188
221
long elapsed = System .currentTimeMillis () - started ;
189
222
if (System .getProperty ("JavacBenchApp.silent" ) == null ) {
190
223
// Set this property when running with "perf stat", etc
191
- System .out .println ("Generated source code for " + bench .sources .size () + " classes and compiled them for " + count + " times in " + elapsed + " ms" );
224
+ System .out .println ("Generated source code for " + bench .sources .size () + " classes and compiled them in " + elapsed + " ms" );
192
225
}
193
226
}
194
227
}
0 commit comments