- define a class loader, extends
URLClassLoader
- define a new public method, call
defineClass
indirectly
public Class<?> loadClassFromBytes(String className, byte[] bytes) {
return this.defineClass(className, bytes, 0, bytes.length);
}
need to use
sun.misc.Unsafe
, which is not recommended
public Class<?> loadClass(String className, byte[] classBytes) {
return UNSAFE.defineAnonymousClass(SimTarget.class, classBytes, EMPTY_OBJECTS);
}
same as jdk8
need to use jvm argument:
--add-exports java.base/jdk.internal.misc=<module>
public Class<?> loadClass(String className, byte[] classBytes) {
return UNSAFE.defineAnonymousClass(AnonClassHolder.class, classBytes, EMPTY_OBJECTS);
}
same as jdk8
use MethodLookup#defineHiddenClass
need to let the hidden class and the holder class in the same package!
public static Class<?> loadClass(String className, byte[] classBytes) {
if (!className.startsWith(PACKAGE_NAME)) {
throw new RuntimeException("not same package, should failed");
}
try {
MethodHandles.Lookup lookup = MethodHandles.lookup();
return lookup.defineHiddenClass(classBytes, true,
MethodHandles.Lookup.ClassOption.NESTMATE,
MethodHandles.Lookup.ClassOption.STRONG)
.lookupClass();
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
-
(
optional
) cddemo-inmem-base
-
(
optional
) compilemvn package -Dmaven.test.skip=true # or mvnd package -Dmaven.test.skip=true
-
(
optional
) callclass2bytes.sh
, generate the Java file, which is hold bytes. -
test in
demo-inmem-jdk8
/demo-inmem-jdk11
/demo-inmem-jdk17