服务器的单独线程中的热重载类

时间:2019-02-11 22:22:36

标签: java java-11 jrebel

我正在研究实现Java类的一些热重装的方法。我正在考虑的技术是这样的:

  1. 将外部/核心库中的所有类保留在内存中
  2. 如果我的文件之一发生更改,请从内存中删除所有 my 类并重新加载我的所有类。我不必重新加载内存中的任何库,因为它们不会更改并且不依赖于我的文件/类。

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)如何将所有库的类保留在内存中,但从内存中删除对我的代码的类/实例的所有引用?

有人认为这种技术有效吗?有可能实现吗?

1 个答案:

答案 0 :(得分:0)

关键概念不是要在Classloader中重新加载类,而是要创建一个单独的ClassLoader实例,以防您执行代码重新加载时被“删除”。可以将未更改的共享库放在您的主项目中,以便可以通过SystemClassLoader使用它们。

创建自定义“ MyClassloader”,并将所有JAR文件及其依赖项加载到其中。 使用MyClassLoader加载并执行已加载代码的主类。

如果要重新加载代码,请停止由可重新加载的代码启动的所有线程。这通常必须由线程本身来支持,例如通过定期检查MyClassLoader全局静态字段AtomicBoolean shutdown并在线程正在等待某些事件的情况下中断线程。

一旦所有线程结束,对代码的唯一引用就是MyClassLoader实例。如果丢掉这个实例,所有代码也将被删除,您可以重新开始。