有没有办法取消定义和重新定义 class 加载程序的 class?
Is there a way to undefine and redefine a class of a class loader?
有没有一种方法可以取消定义和重新定义 class 加载程序的 class 以及编译的另一个运行时 class?
不,没有办法取消定义 class 并重新定义它。
最接近的方法是创建一个新的 classloader 并使用它来加载 class 的新版本。 "hot loading"就是这样实现的。
但是,从 Java 运行时类型系统的角度来看,您实际上是在创建一个新类型。 (JLS 表示具有相同完全限定名称和不同 class 加载器的两个 class 是不同类型。)
备注:
同时拥有一个类型的多个版本会导致不直观的运行时类型错误。
你需要注意2个class加载器之间的关系。如果新的以旧的为父,事情会变得很乱。
这种事情会导致一些相当隐蔽的内存泄漏。虽然 Class
和 ClassLoader
对象可以被垃圾收集,但 classloader、classes 和实例之间存在一些复杂的(隐藏的)依赖关系,这意味着单个可达实例可以导致 classloader 及其所有已加载的 classes 仍然可以访问。
为什么没有办法呢?
一个原因是,它会在 JVM 的运行时类型安全性方面造成巨大的损失。考虑以下序列。
加载以下class
public class Sneaky {
public long x = 42;
}
创建实例
Sneaky s = new Sneaky();
将class重新定义为新版本
public class Sneaky {
public String x;
}
尝试使用我们之前创建的对象的x
字段
System.out.println(s.x.length());
会发生非常糟糕的事情....
有没有一种方法可以取消定义和重新定义 class 加载程序的 class 以及编译的另一个运行时 class?
不,没有办法取消定义 class 并重新定义它。
最接近的方法是创建一个新的 classloader 并使用它来加载 class 的新版本。 "hot loading"就是这样实现的。
但是,从 Java 运行时类型系统的角度来看,您实际上是在创建一个新类型。 (JLS 表示具有相同完全限定名称和不同 class 加载器的两个 class 是不同类型。)
备注:
同时拥有一个类型的多个版本会导致不直观的运行时类型错误。
你需要注意2个class加载器之间的关系。如果新的以旧的为父,事情会变得很乱。
这种事情会导致一些相当隐蔽的内存泄漏。虽然
Class
和ClassLoader
对象可以被垃圾收集,但 classloader、classes 和实例之间存在一些复杂的(隐藏的)依赖关系,这意味着单个可达实例可以导致 classloader 及其所有已加载的 classes 仍然可以访问。
为什么没有办法呢?
一个原因是,它会在 JVM 的运行时类型安全性方面造成巨大的损失。考虑以下序列。
加载以下class
public class Sneaky { public long x = 42; }
创建实例
Sneaky s = new Sneaky();
将class重新定义为新版本
public class Sneaky { public String x; }
尝试使用我们之前创建的对象的
x
字段System.out.println(s.x.length());
会发生非常糟糕的事情....