假设您有两个java类
package package1;
public class SampleClass1 {
public SampleClass1() {
System.out.println("Sample Class Loaded and Called");
}
}
package package1.package2;
import package1.SampleClass1;
public class SampleClass2 {
public SampleClass2() {
new SampleClass1();
System.out.println("Sample Class 2 Loaded and Called");
}
}
并通过ClassLoader加载两个类似的类:
package load;
public class LoadClassFromByteData extends ClassLoader {
private byte[] classByteData;
public LoadClassFromByteData(byte[] classByteData) {
this.classByteData = classByteData;
}
public Class<?> getLoadedClass(String className) {
return defineClass(className, classByteData, 0, classByteData.length);
}
}
//
Class<?> loadedClass1 = loadClassFromByteData.getLoadedClass("package1.SampleClass1");
Class<?> loadedClass2 = loadClassFromByteData.getLoadedClass("package1.package2.SampleClass2");
当我这样调用SampleClass1的构造函数时:
Constructor<?> mainCons1 = loadedClass1.getConstructor();
mainCons1.newInstance();
成功地,打印“加载并调用了示例类”,但是当我从SampleClass2字节数据中调用loadClass2加载的构造函数时,出现错误:
Constructor<?> mainCons2 = loadedClass2.getConstructor();
mainCons2.newInstance();
//是的,首先我加载SampleClass1,然后加载SampleClass2,最后我调用SampleClass2构造函数。
Exception in thread "main" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at db.recorder.deneme.main(deneme.java:48)
Caused by: java.lang.NoClassDefFoundError: package1/SampleClass1
at package1.package2.SampleClass2.<init>(SampleClass2.java:9)
... 5 more
Caused by: java.lang.ClassNotFoundException: package1.SampleClass1
at java.base/java.lang.ClassLoader.findClass(ClassLoader.java:718)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 6 more
我想添加此信息,两个Class字节数据存储在DB中,我从DB获取类的字节数据。实际上,该项目没有任何名为package1或package2的包!
感谢您的回答和建议。
答案 0 :(得分:1)
您需要提供父类加载器。
public static class LoadClassFromByteData extends ClassLoader {
final ConcurrentHashMap<String, Class<?>> definedClassesByName = new ConcurrentHashMap<>();
LoadClassFromByteData(ClassLoader parent) {
super(parent);
}
public Class<?> getLoadedClass(String className, byte[] classAsBytes) {
return this.definedClassesByName.computeIfAbsent(className,
cn -> defineClass(cn, classAsBytes, 0, classAsBytes.length));
}
}
@Test
public void test() throws IOException, InstantiationException, IllegalAccessException {
final byte[] sampleClass1Bytes = Files.readAllBytes(SAMPLE_CLASS1_CLASS_FILE_PATH);
final byte[] sampleClass2Bytes = Files.readAllBytes(SAMPLE_CLASS2_CLASS_FILE_PATH);
final ClassLoader contextClassLoader = Thread.currentThread()
.getContextClassLoader();
final LoadClassFromByteData loadClassFromByteData = new LoadClassFromByteData(contextClassLoader);
final Class<?> sampleClass1 = loadClassFromByteData.getLoadedClass("package1.SampleClass1", sampleClass1Bytes);
final Object sampleClass1Instance = sampleClass1.newInstance();
final Class<
?> sampleClass2 = loadClassFromByteData.getLoadedClass("package1.package2.SampleClass2", sampleClass2Bytes);
final Object newInstance = sampleClass2.newInstance();
}