我正在研究实现Java类的一些热重装的方法。我正在考虑的技术是这样的:
public class Server implements Runnable {
private Thread current;
public void run(){
// create a new classloader and load all my classes from disk?
}
public Server start(){
if(this.current != null){
this.current.destroy(); // not sure if this works
}
this.current = new Thread(r);
this.current.start();
return this;
}
public static void main(String[] args){
var s = new Server().start();
onFileChanges(filePath -> {
// we don't really care what file changed
// as long as it's one of our project's files, we reload all classes
s.start();
});
}
}
我认为关键思想是我可以从项目中重新加载所有类,而不必尝试计算一些依赖树。
我的主要问题是-
(a)如何停止/杀死线程?线程#destroy已弃用。
(b)如何从内存中的类加载器中删除所有类?
(c)如何将所有库的类保留在内存中,但从内存中删除对我的代码的类/实例的所有引用?
有人认为这种技术有效吗?有可能实现吗?
答案 0 :(得分:0)
关键概念不是要在Classloader中重新加载类,而是要创建一个单独的ClassLoader实例,以防您执行代码重新加载时被“删除”。可以将未更改的共享库放在您的主项目中,以便可以通过SystemClassLoader使用它们。
创建自定义“ MyClassloader”,并将所有JAR文件及其依赖项加载到其中。 使用MyClassLoader加载并执行已加载代码的主类。
如果要重新加载代码,请停止由可重新加载的代码启动的所有线程。这通常必须由线程本身来支持,例如通过定期检查MyClassLoader全局静态字段AtomicBoolean shutdown
并在线程正在等待某些事件的情况下中断线程。
一旦所有线程结束,对代码的唯一引用就是MyClassLoader实例。如果丢掉这个实例,所有代码也将被删除,您可以重新开始。