java - 有没有办法取消定义和重新定义类加载器的类?

标签 java classloader

有没有办法用另一个运行时编译的类取消定义和重新定义类加载器的类?

最佳答案

不,没有办法取消定义类并重新定义它。

您最接近的方法是创建一个新的类加载器并使用它来加载该类的新版本。 “热加载”就是这样实现的。

但是,从 Java 运行时类型系统的角度来看,您实际上是在创建一个新类型。 (JLS 说具有相同完全限定名称和不同类加载器的两个类是不同的类型。)

注意事项:

  • 同时拥有一个类型的多个版本可能会导致不直观的运行时类型错误。

  • 您需要注意 2 个类加载器之间的关系。如果新的以旧的为父,事情会变得相当困惑。

  • 这种事情会导致一些相当隐蔽的内存泄漏。虽然 ClassClassLoader 对象可以被垃圾收集,但类加载器、类和实例之间存在一些复杂的(隐藏的)依赖关系,这意味着单个可访问的实例可能会导致类加载器和它所有加载的类仍然可以访问。


为什么没有办法呢?

其中一个原因是,它会严重破坏 JVM 的运行时类型安全性。考虑以下顺序。

  1. 加载下面的类

      public class Sneaky {
          public long x = 42;
      }
    
  2. 创建实例

      Sneaky s = new Sneaky();
    
  3. 将类重新定义为新版本

      public class Sneaky {
          public String x;
      }
    
  4. 尝试使用我们之前创建的对象的x字段。

      System.out.println(s.x.length());
    

    会发生非常糟糕的事情....

关于java - 有没有办法取消定义和重新定义类加载器的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60604281/

相关文章:

Java,比较单个字符串与字符

java - For 循环不终止

java - POST 请求发送 JSON 数据 Java HttpUrlConnection

java - 找不到基于 Spring Boot 表达式的访问控制属性

java - Selenium Wire 日志为空

java - Docker主机之间的Java类路径排序不一致

java - 从 jar 加载自定义类时出现 ClassCastException

java - 设置 WAR 中 jar 的优先顺序

java - 如何在 tomcat 容器中安装 servlet 并将其加载到每个 Web 应用程序的上下文中?

java - 获取String值的ArrayList的值