各种Java热部署插件有什么差别,哪一个最直观易用?

25

我目前正在尝试在Java应用程序中实现热类重新加载,但是有很多插件可供选择,而且我找不到一个好的比较选项之间的区别。此外,插件的网站并不都非常清楚插件的确切功能以及如何使用它们。

还有一种选择是制作自定义热类重新加载ClassLoader,但如果已经有这么多可以完成工作的插件,我觉得这类似于“重复造轮子”..其他人同意这一点吗?

我发现的Java插件,我认为可以胜任这项工作:

那么,有人知道这些插件之间的区别吗?还有哪个插件最直观易用?

补充一点:我想要做的是重新加载我的Java应用程序的.jar文件依赖项。我有一些Java代码,它经常会被自动重新编译,然后转换为一个.jar文件。这是我的Java应用程序的依赖项,我的应用程序需要每次都使用最新版本的这个.jar文件。


1
你可以研究一下使用OSGI。它支持在运行时重新加载bundles。 - Viktor Seifert
3
我使用过Jrebel,对它在项目和依赖项中重新加载类的效果感到惊讶。免费的社交许可证使测试变得容易。JRebel有相当广泛的用户群。 - vcetinick
2
感谢您的评论。我已经在研究OSGi和JRebel,但我还没有决定哪一个对我来说最好。此外,我将把OSGi添加到上面的列表中。 - PJvG
1
@PJvG你能分享一下你的发现吗?你选择了什么,有什么发现吗? - Martin Kersten
2
抱歉让你感到困惑。我只是认为热类重载是某种要求。谢谢你查找它。我看了一下,这个机制有相当有趣的注意事项和边角情况。我自己咬紧牙关,从头开始实现一个类重载机制,因为大多数选项要么是闭源的,要么从我所读的内容中不喜欢实现方式,或者太复杂了。所以再次感谢你的查找。 - Martin Kersten
显示剩余3条评论
2个回答

36

免责声明:我参与了JRebel的开发,因此我的答案可能有一点偏见,但我会尽力解释。

为了回答这个问题,我首先想要引起你的注意的是:你列出的这些名称之间的一个主要区别是:有些解决方案需要你改变应用程序设计,而其他方案则不需要。

模块化解决方案,例如OSGiJBoss模块,如果你遵循正确的路径并对应用程序进行模块化,则提供了好处。否则,如果您部署一个单独的模块,则基本上意味着您正在重新启动/重新部署整个应用程序,从而削弱了此方法所获得的任何好处。

Play Framework实际上是一个全栈框架,具有热部署功能。这些功能取决于您使用的框架版本。但是,与模块化一样,该框架强制执行某种编程模型。

Apache Commons JCI并不是真正用于热更新代码的解决方案。据我所知,它只是通过新的类加载器编译和加载类。这也涉及更改应用程序代码,就像上面提到的情况一样。我不确定这是好还是坏。缺点是您几乎无法通过这种方式与生态系统进行广泛的集成。这种方法对于一个自制框架相当可行,可以利用此功能。我个人更喜欢使用Groovy、 JRuby或JavaScript等脚本语言来实现相同的功能。例如,类似这样的。

JRebelFakereplaceDCEVM - 这些工具不关心编程模型。但它们之间的区别很大:

DCEVM补丁了JVM,并旨在提供完整的热交换解决方案,它确实做到了。

JRebel是一个Java代理(通过-javaagent VM参数连接),它会对应用程序代码进行仪器化,并通过版本控制加载新版本的类。JRebel的主要价值在于,它提供灵活的配置以及大量特定于框架的集成,因此您不仅可以仅热交换Java类,还可以添加和自动装配Spring应用程序上下文中的新bean,实时添加新的EJBs和Struts操作等。

Fakereplace也是一种仪器化代理,像JRebel一样,但它对Java代码更改的支持要少得多(我假设),并且支持的框架数量也不那么令人印象深刻。

Feenix可以做到Java Instrumentation API允许其做的事情。这基本上意味着它并没有真正增加除JVM标准热交换之外的价值。同样适用于AgentSmith

更新:此答案激励了Feenix作者推出了一个新版本-Feenix 2.0,它与JRebel处理类的方式相似。但正如作者自己所说,Feenix仍然远远不及JRebel。还有一些类似的解决方案,如HotswapAgentSpring Loaded -这些工具也提供类似的功能,但在各自的方式上受到限制。

现在来谈谈您的具体问题,以及如何使用JRebel解决它:

应用程序的每个模块都应该有自己的配置文件,rebel.xml。所谓模块,包括 EAR、WAR 或 WEB-INF/lib 中的任何 JAR 依赖项(例如您的情况),或者特定于服务器的库。配置文件将指向编译类所在的目录,JRebel 将直接从该位置加载类。这意味着当您更改 Java 类时,无需组装整个 JAR 文件。 相反地,您进行更改并编译源代码(利用 IDE 而不是构建脚本)。一旦在应用程序代码中调用该类,JRebel 将重新加载编译后的类。


1
非常感谢详细的回答,对我很有帮助。但您的回答中没有提到Apache Commons JCI FAM和AgentSmith,是否有原因呢? - PJvG
1
由于ZeroTurnaround取消了其浮动许可证模式,我正在寻找JRebel的替代方案,并找到了这个很棒的答案。与此同时,有一个新的童子军:https://github.com/spring-projects/spring-loaded。它确实有一些限制,但它所做的事情做得很好。 - Marcel Stör

2

最近出现了一个新的工具,RelProxy,它是开源的,并且虽然不像JRebel那样高级,但它可以用于在运行时自由更改您代码的子集,并且重新加载几乎没有性能损失并且无需重新加载上下文(不会丢失会话)。这对于开发和生产环境都是免费的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接