44import org .junit .jupiter .api .Test ;
55import org .junit .jupiter .api .Assertions ;
66import org .junit .jupiter .api .io .TempDir ;
7+ import org .objectweb .asm .ClassReader ;
8+ import org .objectweb .asm .Opcodes ;
79
810import javax .tools .JavaCompiler ;
911import javax .tools .ToolProvider ;
1921import java .util .*;
2022import java .util .concurrent .atomic .AtomicBoolean ;
2123import java .util .stream .Collectors ;
24+ import java .util .zip .ZipEntry ;
25+ import java .util .zip .ZipInputStream ;
2226
2327@ Tag ("benchmark" )
2428public class HeavyLoadBenchmarkTest {
@@ -45,26 +49,47 @@ public void benchmarkJavaAPITranslation() throws Exception {
4549 Files .createDirectories (srcDir );
4650 Files .createDirectories (classesDir );
4751
48- // Create a heavy main class that references various parts of the API to force traversal
52+ // Scan JavaAPI for public classes to generate a heavy load
53+ List <String > publicClasses = scanPublicClasses (javaApiJar );
54+ System .out .println ("Found " + publicClasses .size () + " public classes in JavaAPI." );
55+
56+ // Create a heavy main class that references these classes
4957 Path pkgDir = srcDir .resolve ("com" ).resolve ("benchmark" );
5058 Files .createDirectories (pkgDir );
5159 Path javaFile = pkgDir .resolve ("BenchmarkMain.java" );
52- String source = "package com.benchmark;\n " +
53- "public class BenchmarkMain {\n " +
54- " public static void main(String[] args) {\n " +
55- " java.util.ArrayList l = new java.util.ArrayList();\n " +
56- " l.add(\" Hello\" );\n " +
57- " java.util.HashMap m = new java.util.HashMap();\n " +
58- " m.put(\" Key\" , l);\n " +
59- " System.out.println(m);\n " +
60- " java.util.Vector v = new java.util.Vector();\n " +
61- " v.addElement(new java.util.Date());\n " +
62- " try {\n " +
63- " Class.forName(\" java.util.TimeZone\" );\n " +
64- " } catch (Exception e) {}\n " +
65- " }\n " +
66- "}" ;
67- Files .write (javaFile , source .getBytes ());
60+
61+ StringBuilder source = new StringBuilder ();
62+ source .append ("package com.benchmark;\n " );
63+ source .append ("public class BenchmarkMain {\n " );
64+ source .append (" public static void main(String[] args) {\n " );
65+ source .append (" System.out.println(\" Starting benchmark...\" );\n " );
66+
67+ // Split into chunks to avoid method size limits
68+ int methodCount = 0 ;
69+ int chunkSize = 500 ;
70+ for (int i = 0 ; i < publicClasses .size (); i += chunkSize ) {
71+ source .append (" loadChunk" ).append (methodCount ++).append ("();\n " );
72+ }
73+ source .append (" }\n " );
74+
75+ methodCount = 0 ;
76+ for (int i = 0 ; i < publicClasses .size (); i += chunkSize ) {
77+ source .append (" private static void loadChunk" ).append (methodCount ++).append ("() {\n " );
78+ source .append (" try {\n " );
79+ source .append (" Class[] classes = new Class[] {\n " );
80+ int end = Math .min (i + chunkSize , publicClasses .size ());
81+ for (int j = i ; j < end ; j ++) {
82+ String clsName = publicClasses .get (j );
83+ // Use Class.forName to avoid compilation issues with package-private classes/inner classes
84+ source .append (" Class.forName(\" " ).append (clsName ).append ("\" ),\n " );
85+ }
86+ source .append (" };\n " );
87+ source .append (" } catch (Throwable t) {}\n " );
88+ source .append (" }\n " );
89+ }
90+ source .append ("}\n " );
91+
92+ Files .write (javaFile , source .toString ().getBytes ());
6893
6994 // Compile the benchmark main
7095 JavaCompiler compiler = ToolProvider .getSystemJavaCompiler ();
@@ -146,9 +171,32 @@ private void runTranslator(String classpath, Path outputDir) throws Exception {
146171 }
147172 }
148173
174+ private List <String > scanPublicClasses (Path jarFile ) throws IOException {
175+ List <String > classes = new ArrayList <>();
176+ try (ZipInputStream zis = new ZipInputStream (Files .newInputStream (jarFile ))) {
177+ ZipEntry ze ;
178+ while ((ze = zis .getNextEntry ()) != null ) {
179+ if (ze .getName ().endsWith (".class" ) && !ze .getName ().startsWith ("META-INF" )) {
180+ try {
181+ ClassReader cr = new ClassReader (zis );
182+ if ((cr .getAccess () & Opcodes .ACC_PUBLIC ) != 0 ) {
183+ String name = cr .getClassName ().replace ('/' , '.' );
184+ if (!name .contains ("-" ) && !name .equals ("module-info" )) {
185+ classes .add (name );
186+ }
187+ }
188+ } catch (Exception e ) {
189+ // ignore bad classes
190+ }
191+ }
192+ }
193+ }
194+ return classes ;
195+ }
196+
149197 private void unzip (Path zipFile , Path outputDir ) throws IOException {
150- try (java . util . zip . ZipInputStream zis = new java . util . zip . ZipInputStream (Files .newInputStream (zipFile ))) {
151- java . util . zip . ZipEntry ze = zis .getNextEntry ();
198+ try (ZipInputStream zis = new ZipInputStream (Files .newInputStream (zipFile ))) {
199+ ZipEntry ze = zis .getNextEntry ();
152200 while (ze != null ) {
153201 Path newFile = outputDir .resolve (ze .getName ());
154202 if (ze .isDirectory ()) {
0 commit comments