gpt4 book ai didi

java - 动态加载后调用时出现 ClassNotFoundException

转载 作者:行者123 更新时间:2023-12-02 11:33:18 26 4
gpt4 key购买 nike

我试图让应用程序动态加载某些类,然后调用启动方法,但问题是,由于 ClassLoader 不同,一个类无法调用另一个类的方法,但是正如我已经用 google 搜索的那样,我用父类创建了两个类加载器。这是我的测试类:

public class Plugin {
public static void main(String[] args) throws Exception {
Class<?> fii = loadClass(new File("Fii.class"), "ua.i0xhex.plugin.Fii");
Class<?> goo = loadClass(new File("Goo.class"), "ua.i0xhex.plugin.Goo");
goo.getMethod("hello", new Class<?>[0]).invoke(goo.newInstance(), (Object[]) null);
}

public static Class<?> loadClass(File file, String name) throws Exception {
DLoader loader = new DLoader(Plugin.class.getClassLoader());
byte[] data = toByte(file);
Class<?> clazz = loader.defineClass(name, data);
return clazz;
}

public static byte[] toByte(File file) throws Exception {
FileInputStream inputStream = new FileInputStream(file);
ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
int count;
byte[] bytes = new byte[1024];
while ((count = inputStream.read(bytes, 0, bytes.length)) != -1)
byteOutputStream.write(bytes, 0, count);
inputStream.close();
return byteOutputStream.toByteArray();
}

public static class DLoader extends ClassLoader {
public DLoader(ClassLoader parentLoader) {
super(parentLoader);
}
public Class<?> defineClass(String name, byte[] b) {
return super.defineClass(name, b, 0, b.length);
}
}
}

我已经在我的测试应用程序附近编译并复制了两个类。 Goo.hello() 必须打印“Hello World”,然后调用 Fii.hi()

输出:

Hello World!
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at ua.i0xhex.plugin.Plugin.main(Plugin.java:11)
Caused by: java.lang.NoClassDefFoundError: ua/i0xhex/plugin/Fii
at ua.i0xhex.plugin.Goo.hello(Goo.java:11)
... 5 more
Caused by: java.lang.ClassNotFoundException: ua.i0xhex.plugin.Fii
at java.lang.ClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 6 more

如何确保我的动态加载类能够调用另一个加载类的方法?如果我为这两个类创建 1 个 ClassLoader,则一切正常,但在实际工作中不会只有一个。

最佳答案

每次调用 loadClass 方法时都会定义一个新的类加载器

 DLoader loader = new DLoader(Plugin.class.getClassLoader());

然后您使用该类加载器来加载您的类。通过这种方式,您可以获得一个用于 Fii 的类加载器和一个用于 Goo 的类加载器,并且具有相同的父类加载器。

您可能希望它们都使用相同的类加载器,因此您可能希望将其作为参数传递给您的 loadclass 方法,如下所示:

public static void main(String[] args) throws Exception {
DLoader loader = new DLoader(Plugin.class.getClassLoader())
Class<?> fii = loadClass(loader, new File("Fii.class"), "ua.i0xhex.plugin.Fii");
Class<?> goo = loadClass(loader, new File("Goo.class"), "ua.i0xhex.plugin.Goo");
goo.getMethod("hello", new Class<?>[0]).invoke(goo.newInstance(), (Object[]) null);
}

public static Class<?> loadClass(DLoader loader, File file, String name) throws Exception {
byte[] data = toByte(file);
Class<?> clazz = loader.defineClass(name, data);
return clazz;
}

如果您喜欢该路线,您当然也可以将类加载器存储为静态变量

关于java - 动态加载后调用时出现 ClassNotFoundException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49129723/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com