【问题标题】:Java Class Loader Russian DollsJava 类加载器俄罗斯娃娃
【发布时间】:2016-06-23 20:32:42
【问题描述】:

是否可以在 Java 中创建一个加载(或更恰当地重新加载)自身的类加载器?

它最初可以由默认的类加载器加载。我想象一个 Java 系统,它能够在通过编译和加载周期运行时进行自我修改。如果是这样,您可以创建许多继承自俄罗斯娃娃加载器的对象,以动态更新它们的逻辑。

【问题讨论】:

  • 不加载自己加载怎么办?
  • 它最初会由默认的类加载器加载。
  • 您是否尝试重新加载类加载器本身?
  • 这是问题的核心。是的。更具体地说,从自己的逻辑重新加载类......而不是不同类中的逻辑。
  • 你能描述一下你想做什么吗?听起来您在问如何最好地实施一种方法来实现基本目标,但最好退后一步,问问这是否是最好的方法。

标签: java compilation jvm classloader dynamic-class-loaders


【解决方案1】:

您可以在另一个ClassLoader 中重新加载每个限定名称不以java. 开头的类的代码,但这不会重新加载该类。相反,它会创建一个具有相同限定名称但定义不同的新类 ClassLoader。

见The Java® Virtual Machine Specification, §5.3. Creation and Loading

类加载器L 可以通过直接定义或委托给另一个类加载器来创建C。如果L 直接创建C,我们说L 定义 C 或者,等效地,L 是C 的定义加载器 .
…
在运行时,一个类或接口不仅仅由其名称决定,而是由一对:它的二进制名称(第 4.2.1 节)和它的定义类加载器决定。

因此,当您使用不同的类加载器实例定义一个与现有类具有相同限定名称的类时,您实际上是在创建一个新的运行时类。当然,该类可能会扩展 ClassLoader 并且可以用于再次定义具有相同限定名称的新类。

这些新类是否具有相同的字节码、修改后的版本或完全不相关,都无关紧要。

这与大多数支持重新加载模块的框架的工作方式很接近。他们创建了一个新的类加载器(但不是旧的子类),它将“重新加载”一个模块的所有类,包括未更改的类,因为从技术上讲,它创建了一个新的不相关的动物园必须相互链接的类。
然后旧类必须超出范围,这需要小心。类加载器只能在其所有类都未使用的情况下进行垃圾回收。一个类的单个实例可能会阻止其类加载器及其所有定义的类被垃圾收集......

【讨论】:

  • 谢谢,很好的回答。那么,对于一个类要成功地重新加载自己,它是否必须:1.)摆脱旧版本的自身(这是不可能的,因为每个类都维护一个父类加载器变量)和 2.)更新所有链接?如果这是真的,那么答案是否定的,不可能。
  • 确实,无法为ClassLoader 实现完全重新加载的语义(只能通过委派给实际工作的另一个ClassLoader)。这并不是要与通过 Instrumentation API 进行的真正重新加载相混淆,这种真正的重新加载有几个限制,并且不会更改定义的 ClassLoader。
猜你喜欢
  • 1970-01-01
  • 2014-03-19
  • 1970-01-01
  • 2020-07-01
  • 2016-07-20
  • 1970-01-01
  • 1970-01-01
  • 2014-11-05
  • 1970-01-01
相关资源
最近更新 更多