当前位置: 首页 > 面试题库 >

用于重载类的各种Java插件之间有什么区别,哪个是最直观的?

班浩皛
2023-03-14
问题内容

我目前正在尝试在Java应用程序中实现 热类重载 ,但是有太多的插件可供选择,我在这些选项之间找不到很好的 比较
。此外,插件的网站还不清楚其确切 功能 以及如何使用它们。

还有一个选项可以使 自定义的热门类重新加载ClassLoader ,但是如果已经有很多可以完成此工作的插件,我觉得这类似于 “重新发明轮子”
。其他人也同意吗?

我发现可以完成此任务的Java插件:

  • 叛逆者
  • 动态代码演化虚拟机(DCEVM)
  • 假货
  • Apache Commons Java编译器接口(JCI)FileAlterationMonitor(FAM)
  • 史密斯
  • 菲尼克斯
  • 播放框架
  • JBoss / WildFly
  • OSGi

那么,有没有人碰巧知道插件之间的 区别 呢?还有哪个插件使用起来最 直观

附带说明:我真正想做的是重新加载Java应用程序的.jar文件依赖项。我有一些Java代码,这些代码经常会自动重新编译,然后转换为.jar文件。这是我的Java应用程序的依赖项,我的应用程序每次都需要使用此.jar文件的最新版本。


问题答案:

免责声明: 我参与了JRebel开发,因此我的回答可能看起来有些偏颇,但是我会尽力解释。

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

模块化解决方案,如 OSGi的JBoss的模块 提供的好处,如果你按照正确的道路和 模块化
应用程序。否则,如果部署一个孤岛捆绑包,则基本上意味着您要重新启动/重新部署整个应用程序,从而削弱了从这种方法中获得的任何好处。

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

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

JRebelFakereplaceDCEVM- 那些家伙不在乎编程模型。但是差异很大:

DCEVM 对JVM进行了修补,其目标是提供一个完整的热交换解决方案。

JRebel 是一个Java代理(与-javaagent
VM参数挂钩),它检测应用程序代码并通过对类的新版本进行加载。JRebel的主要价值在于它提供了灵活的配置以及大量特定于框架的集成,因此您不仅可以完成Java类的热交换,还可以做更多的事情。例如,在Spring应用程序上下文中添加和自动装配新bean,动态添加新的EJB,以及新的Struts操作,等等。

Fakereplace 也是插桩剂,如 JRebel的
,但它对于Java代码的变化少了很多的支持(我认为),并支持框架的数量是不一样令人印象深刻。

Feenix* 可以完成Java Instrumentation
API所允许的所有工作。这基本上意味着它并没有真正在JVM的标准HotSwap之上增加价值。与 AgentSmith 相同
*

更新:这个答案促使Feenix的作者提出了一个新版本 -Feenix 2.0 ,它类似于JRebel与类一起工作的方式。但是正如作者自己说的那样-
Feenix仍然远不及JRebel。还有一些类似的解决方案,例如 HotswapAgentSpring Loaded-
这些工具也提供了类似的功能,但受其自身方式的限制。

现在介绍您的特定问题 ,如何使用JRebel解决:

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



 类似资料:
  • 我的客户问我使用 NFS 时是否有任何区别,如下所示: 方法 1:定义 PV,如下所示: apiVersion:v1 种类:PersistentVolume 元数据: 名称:mysqldb volume 规格: capacity: 存储:3Gi 访问模式: 1ReadWriteMany nfs: path:/var/export/dbvol 服务器:master.lab.example。com 方

  • 在任何人告诉我查找旧答案或RTFM之前,请注意我已经这样做了,所以请在指示我查找其他地方之前阅读详细信息。 我已经确定,优化级别的差异并不像为更高的优化级别启用了一些不同类型的优化标志那么简单。 例如,我首先通过以下步骤发现了O0和O1的优化标志的差异: 这给了我一个O1对O0启用的各种优化标志的列表。 然后,我用-O0编译了代码,但是添加了O1对O0启用的所有单独的优化标志,因为结果应该和O1一

  • 问题内容: Java 和类之间有什么区别? 问题答案: BufferedReader是“ InputStreamReader / FileReader”的包装,它在每次调用本机I / O时都缓冲信息。 您可以想象在读取一个字符(或字节)与读取一个大号时的效率差异。一圈(或字节)中的字符数。使用BufferedReader,如果您希望读取单个字符,它将存储内容以填充其缓冲区(如果为空),并且对于进一

  • 问题内容: 重载方法和覆盖方法有什么区别?谁能举例说明? 问题答案: 方法重载涉及在同一个类中具有相同名称但参数不同的两个或多个方法的概念。 方法覆盖是指具有相同参数但实现不同的两个方法。其中一个将存在于父类中,而另一个将存在于派生类或子类中。的注释,而不是必需的,可以是有帮助的执行的方法的适当的首要在编译时。

  • 问题内容: 和之间有什么区别 例如,当你查看类时,构造函数具有以下签名: 对于方法之一: 问题答案: 第一个说是“是E的祖先的某种类型”。第二个说是“某种类型,它是E的子类”。(在两种情况下,本身都可以。) 因此,构造函数使用该? 形式,以确保在从集合中获取值时,它们将全部为E或某个子类(即,它是兼容的)。该方法试图将值放入集合中,因此集合必须具有 或超类的元素类型。 例如,假设你有一个这样的类层

  • 问题内容: 两种方法是相同的还是要注意的主要差异/陷阱? 问题答案: 主要区别是基于类的可变单例有效,而基于结构的可变“单例”无效。除非您想使单身人士不可变(这是很少见的),否则您应该坚持基于类的方式。 这是一个可变的基于结构的“单身”如何工作的例证。考虑将可变成员添加到两个单例中,如下所示: 我做了一个,但是我可以将其公开为只读属性和一个变异方法。重要的是这两种类型现在都是可变的。 如果我这样做