- 定义一个类加载器,继承
URLClassLoader - 定义一个新方法,间接调用
defineClass
public Class<?> loadClassFromBytes(String className, byte[] bytes) {
return this.defineClass(className, bytes, 0, bytes.length);
}需要用不被建议使用的
sun.misc.Unsafe
public Class<?> loadClass(String className, byte[] classBytes) {
return UNSAFE.defineAnonymousClass(SimTarget.class, classBytes, EMPTY_OBJECTS);
}同 jdk8
需要添加
JVM参数:--add-exports java.base/jdk.internal.misc=<module>
public Class<?> loadClass(String className, byte[] classBytes) {
return UNSAFE.defineAnonymousClass(AnonClassHolder.class, classBytes, EMPTY_OBJECTS);
}同 jdk8
使用 MethodLookup#defineHiddenClass
需要让被隐藏的类和持有类在同一个
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);
}
}-
(
可选) 切换到demo-inmem-base -
(
可选) 编译mvn package -Dmaven.test.skip=true # or mvnd package -Dmaven.test.skip=true -
(
可选) 执行class2bytes.sh, 生成持有class bytes的 Java 文件. -
在
demo-inmem-jdk8/demo-inmem-jdk11/demo-inmem-jdk17中测试