1414import java .io .IOException ;
1515import java .io .OutputStream ;
1616import java .lang .reflect .Constructor ;
17+ import java .lang .invoke .MethodHandles ;
1718import java .net .URI ;
1819import java .util .ArrayList ;
1920import java .util .List ;
@@ -70,8 +71,7 @@ private static JsonPath compileAst(JavaCompiler compiler, JsonPathAst.Root ast)
7071
7172 private static JsonPath instantiate (String fqcn , Map <String , byte []> bytecode ) {
7273 try {
73- final var loader = new InMemoryClassLoader (JsonPathCompiler .class .getClassLoader (), bytecode );
74- final Class <?> clazz = loader .loadClass (fqcn );
74+ final Class <?> clazz = defineInThisLoader (fqcn , bytecode );
7575 if (!JsonPath .class .isAssignableFrom (clazz )) {
7676 throw new IllegalStateException ("Generated class does not implement JsonPath: " + fqcn );
7777 }
@@ -85,6 +85,30 @@ private static JsonPath instantiate(String fqcn, Map<String, byte[]> bytecode) {
8585 }
8686 }
8787
88+ private static Class <?> defineInThisLoader (String fqcn , Map <String , byte []> bytecode ) {
89+ final var bytes = bytecode .get (fqcn );
90+ if (bytes == null ) {
91+ throw new IllegalStateException ("Missing bytecode for generated class: " + fqcn );
92+ }
93+ try {
94+ // Define into the same loader/package as JsonPathCompiler so package-private helpers are accessible.
95+ final MethodHandles .Lookup lookup = MethodHandles .lookup ();
96+ // Define any nested classes first, then the main (or vice versa) doesn't matter for our current codegen.
97+ for (final var entry : bytecode .entrySet ()) {
98+ if (!entry .getKey ().equals (fqcn )) {
99+ try {
100+ lookup .defineClass (entry .getValue ());
101+ } catch (LinkageError ignored ) {
102+ // Best-effort: might already be defined in this JVM.
103+ }
104+ }
105+ }
106+ return lookup .defineClass (bytes );
107+ } catch (IllegalAccessException ex ) {
108+ throw new IllegalStateException ("Failed to define generated class in current loader: " + fqcn , ex );
109+ }
110+ }
111+
88112 private static Map <String , byte []> compileToBytes (JavaCompiler compiler , String fqcn , String javaSource ) {
89113 final var diagnostics = new DiagnosticCollector <JavaFileObject >();
90114
@@ -340,22 +364,5 @@ Map<String, byte[]> bytecode() {
340364 }
341365 }
342366
343- private static final class InMemoryClassLoader extends ClassLoader {
344- private final Map <String , byte []> bytecode ;
345-
346- InMemoryClassLoader (ClassLoader parent , Map <String , byte []> bytecode ) {
347- super (parent );
348- this .bytecode = bytecode ;
349- }
350-
351- @ Override
352- protected Class <?> findClass (String name ) throws ClassNotFoundException {
353- final var bytes = bytecode .get (name );
354- if (bytes == null ) {
355- return super .findClass (name );
356- }
357- return defineClass (name , bytes , 0 , bytes .length );
358- }
359- }
360367}
361368
0 commit comments