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

问题描述 投票:0回答:1

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

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

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个回答
0
投票

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

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.