为什么Java的调试热交换仅限于方法内更改?

2022-09-01 17:31:34

我已经完成了热部署教程,它的工作原理。但是我对限制(第3点)有疑问,即

热部署仅支持方法实现中的代码更改。如果添加新类或新方法,仍需要重新启动。

基本上,如果我在现有方法中进行更改,我们不需要重新启动服务器,但在添加方法或类的情况下需要。

我对它如何运作的理解:-当我在现有方法中进行更改或引入新方法时,Eclipse会将文件放在Web服务器下的正确位置。如果类已经由类装入器在烫发器中加载,它将从permgen空间中卸载它,并在内部加载新的类,而无需重新启动服务器,以便反映新的更改(字节码)。这是对的吗?

如果是,为什么热部署不适用于新方法和新类文件?


答案 1

推理相当复杂,只有对JVM及其如何管理内存有深入了解的人才能完全了解。这里有一个不错的解释:Java HotSwap Guide(尽管它实际上是JRebel产品的广告) - 滚动到标题为“为什么HotSwap仅限于方法体?”的部分

要点:有两个主要因素阻止HotSwap处理类的结构更改:JIT和内存分配。

JVM 中的 JIT(Just In Time)编译器在类加载并运行几次后优化字节码,基本上内联了许多提高性能的调用。在类签名和结构可以更改的环境中安全有效地实现该功能将是一项重大挑战。

其他问题围绕着如果允许类结构更改将会发生什么有关内存管理的问题。JVM 必须修改类的现有实例,这意味着将它们重新定位到堆存储的其他部分。更不用说必须重新定位类对象本身了。JVM的内存管理已经非常复杂和高度优化。此类更改只会增加复杂性并可能降低 JIT 编译器的性能(并可能导致其他错误)。

我认为可以安全地假设JVM工程师不愿意进行支持此功能所需的性能和错误占用空间权衡。这就是为什么像JRebel和其他产品这样的产品已经存在的原因。


答案 2

作为旁注,规范本身不受限制

只是碰巧一些可用的实现,包括无处不在的参考实现,是有限的。

连接到远程 VM 后,可以检查它是否允许添加方法重新定义类