【问题标题】:Hot reload classes in separate thread of server在服务器的单独线程中热重载类
【发布时间】:2019-02-11 22:22:36
【问题描述】:

我正在研究实现 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) 如何停止/终止线程? Thread#destroy 已弃用。

(b) 如何从内存中的类加载器中删除所有类?

(c) 如何将库的所有类保留在内存中,但从内存中删除对我的代码的类/实例的所有引用?

有人认为这种技术会奏效吗?是否可以实现?

【问题讨论】:

标签: java java-11 jrebel


【解决方案1】:

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

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

如果您想重新加载代码,请停止由可重新加载代码启动的所有线程。这通常必须由线程本身支持,例如通过定期检查 MyClassLoader 全局静态字段 AtomicBoolean shutdown 加上中断线程以防它正在等待某些东西。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-09
    • 1970-01-01
    • 2018-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-06
    • 2022-12-19
    相关资源
    最近更新 更多