我正在编写一个应用程序,需要在运行时重新加载先前加载的类。原因是该类是在运行时自动生成的,并且新的实现改变了应用程序的工作方式。我只生成该类的一个对象,并将其从所有依赖项中剥离,只保留一个定义常量值的接口(interface)。重新加载时重置任何或所有成员的值都没有问题。我确切地知道它什么时候发生变化并且我可以控制它。我遇到的唯一问题是重新加载本身。
根据我的阅读,我应该使用类加载器。我尝试这样做,但无法成功。
我尝试了以下方法:
- 获取当前的 ClassLoader (
myClassObject.getClass().getClassLoader()
) 并使用它重新加载类 - 不起作用。它可能会继续加载旧的实现。 - 生成我自己的(又名从 SO 复制粘贴并进行修改)- 不起作用,因为我生成的 ClassLoader 与生成该类的 ClassLoader 不同(异常(exception):myClass 无法转换为 myClass)。
- 创建一个设置父类(super class)的 ClassLoader 的构造函数似乎没有任何效果。
- 使用我的新 ClassLoader 生成以 myClassObject 作为成员的类,解决了 myClassObject 的 ClassLoader 不匹配问题,但在上一级创建了一个新的不匹配问题。我每次都使用
getClassLoader()
,但发现它们不匹配。 - 我尝试添加
-Djava.system.class.loader=com.test.Reoader com.test.myMainClass
以使其成为我的默认重新加载器,但编译器出现错误。 - Google 不断将我指向我已经读过的相同内容。
- 编辑:我尝试创建一个接口(interface)并重新加载实现它的类。这也没有解决问题。
我知道我应该重写默认的类加载器,但我所做的一切似乎都没有成功。
我的类加载器:
public class Reloader extends ClassLoader {
public Reloader(){
super(Reloader.class.getClassLoader());
}
@Override
public Class<?> loadClass(String s) {
return findClass(s);
}
@Override
public Class<?> findClass(String s) {
try {
byte[] bytes = loadClassData(s);
return defineClass(s, bytes, 0, bytes.length);
} catch (IOException ioe) {
try {
return super.loadClass(s);
} catch (ClassNotFoundException ignore) {}
ioe.printStackTrace(java.lang.System.out);
return null;
}
}
private byte[] loadClassData(String className) throws IOException {
File f = new File("out\\production\\ManoCPU\\" + className.replaceAll("\\.", "/") + ".class");
int size = (int) f.length();
byte buff[] = new byte[size];
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
dis.readFully(buff);
dis.close();
return buff;
}
}
非常感谢任何可以提供帮助的人。
最佳答案
您只能加载一个类一次(每个类加载器的实例)。这意味着您必须丢弃用于加载类的类加载器,并为该类的更新版本实例化一个新的类加载器。
在处理多个类加载器时,还请记住,如果您使用多个类加载器加载同一个类,则它们不会被识别为同一个类。
关于java - 如何重新加载先前加载的在运行时更改的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16618225/