我正在编写一个需要在运行时重新加载以前加载的类的应用程序。原因是该类是在运行时自动生成的,而新的实现改变了应用程序的工作方式。我只生成了该类的一个对象,并且我将它从所有依赖项中剥离了一个定义常量值的接口。重新加载时重置任何或所有成员的值没有问题。我确切地知道它什么时候改变并且我可以控制它。我唯一的问题是重新加载本身。
根据我的阅读,我应该使用 ClassLoader。我试图这样做,但我无法让它工作。
我尝试了以下方法:
- 获取当前的 ClassLoader (
myClassObject.getClass().getClassLoader()
) 并使用它重新加载类 - 不起作用。它可能会继续加载旧的实现。 - 生成我自己的(也就是从 SO 复制粘贴并进行修改) - 不起作用,因为我生成的 ClassLoader 与生成该类的 ClassLoader 不同(例外:无法将 myClass 强制转换为 myClass)。
- 创建一个设置超类的 ClassLoader 的构造函数似乎没有任何效果。
- 使用我的新 ClassLoader 生成以 myClassObject 作为成员的类解决了 myClassObject 的 ClassLoader 不匹配问题,但又创建了一个新的不匹配级别。我
getClassLoader()
每次都用,我发现它们不匹配。 - 我尝试添加
-Djava.system.class.loader=com.test.Reoader com.test.myMainClass
使其成为我的默认重新加载器,但我从编译器中得到一个错误。 - 谷歌不断将我指向我已经阅读过的相同内容。
- 编辑:我尝试创建一个接口并重新加载实现它的类。那也没有解决。
我知道我应该覆盖默认的 ClassLoader,但我所做的一切似乎都没有成功。
我的类加载器:
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;
}
}
非常感谢任何可以提供帮助的人。