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

时间:2015-12-26 16:26:57

标签: java debugging hotdeploy jpda

我经历了hot deployment tutorial并且它有效。 但我对限制有疑问(第3点),即

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

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

我理解它的工作原理: - 当我在现有方法中进行更改或引入新方法时,Eclipse会将文件放在正确的位置 在网络服务器下。如果类已经由perm gen空间中的类加载器加载,它将从permgen空间卸载它并在内部加载新的那个而不重新启动服务器,以便反映新的更改(字节代码)。那是对的吗 ?

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

4 个答案:

答案 0 :(得分:23)

这个推理非常复杂,只有熟悉JVM以及如何管理内存的人才能完全了解。有一个不错的解释at this page(虽然它确实是JRebel产品的广告) - 滚动到标题为为什么HotSwap仅限于方法体?的部分。

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

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

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

我认为可以安全地假设JVM工程师不愿意采用支持此功能所需的性能和错误足迹权衡。这就是为什么JRebel等产品应该存在的原因。

答案 1 :(得分:2)

作为旁注,规范本身是not limited

只是发生了一些可用的实现,包括无处不在的Reference Implementation,是有限的。

连接到远程VM后,您可以检查它是否允许add methodsredefine classes

答案 2 :(得分:2)

如果你在smalltalk vm上运行java,你可以。 Smalltalk基本上是永远这样做的,这也是Smalltalkers倾向于将调试器驱动的开发作为一种优秀的测试驱动开发形式的原因之一。 Smalltalk vms执行所需的内存数据结构清理。在Eliot Miranda的Spur(对于Squeak,Pharo和Cuis)和Gemstone懒惰地完成,但是否则你可能不得不等待所有对象被迁移。参考实现java vm可能比你在a.t.m上运行java的任何smalltalk vm有更多的优化。

答案 3 :(得分:0)

E-Riz提供的答案已经很好地解释了标准Java HotSwap技术仅支持对现有方法的修改而不是向类添加新类或方法的原因。

但是,正如相关SO discussion中所描述的那样,您实现的热交换级别取决于您使用的工具链。因此,如果最终添加JRebel插件,即使添加了新的方法和类,也可以执行热交换。

还有另一个项目:Hot Swap Agent - 这通常是一个可用于运行Java容器的java代理,您可以使用几个命令行参数激活它(如{{3}中所述) })。