Skip to content

Commit 3414294

Browse files
cursoragentsimbo1905
andcommitted
Issue #128 Define generated JsonPath in same loader
Co-authored-by: simbo1905 <simbo1905@60hertz.com>
1 parent f82b0ed commit 3414294

File tree

1 file changed

+26
-19
lines changed

1 file changed

+26
-19
lines changed

json-java21-jsonpath/src/main/java/json/java21/jsonpath/JsonPathCompiler.java

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.io.IOException;
1515
import java.io.OutputStream;
1616
import java.lang.reflect.Constructor;
17+
import java.lang.invoke.MethodHandles;
1718
import java.net.URI;
1819
import java.util.ArrayList;
1920
import 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

Comments
 (0)