java - 在运行时替换某些方法的内容

标签 java playframework runtime classloader javassist

我想在运行时替换一些方法的内容。

我知道我可以为此使用 javassist,但它不起作用,因为我想增强的类已经由系统 classLoader 加载。

如何在运行时替换方法的内容?我应该尝试卸载类(class)吗?我怎样才能做到这一点 ?我看到这是可能的,但我不知道该怎么做。

如果可能,我想避免为此使用外部库,我想自己编写代码。

更多信息: - 我想增强的类包含在一个框架中(在一个 jar 文件中) - 我的代码实际上是这个框架的一个插件 - 我的插件运行的框架有它自己的classLoader,但是这个classLoader不加载它自己的类(它把它们委托(delegate)给系统类加载器) - 我使用的框架是Play

感谢您的帮助!

最佳答案

可以使用 Javaassist 以及任何其他字节码工程库来完成。神奇之处在于 Java Attach API,它允许程序附加到正在运行的 JVM(并修改加载的类)。

可以在 com.sun.tools.attach 中找到包,顾名思义,是特定于 Oracle JVM 的。尽管如此,jstackjmap 等 JDK 工具使用它来支持它们的“附加到正在运行的 JVM”功能,因此可以肯定地说它会继续存在。

Attach API 上的文档描述性很强,而这个 Oracle blog post演示在运行时附加代理。一般来说,它归结为:

  • 使用 premain 等以“常规”-javaagent 方式制作重新转换程序
  • premain 重命名为 agentmain
  • 创建一个临时 JAR 文件,其中包含您的代理类并有一个 list 将 Agent-Class 指向您的代理(agentmain-包含)类,并且 可以- Retransform-Classes 设置为 true
  • 获取目标JVM(可能是同一进程)的PID,并将临时jar附加到它上面

谢天谢地,API 无需您做太多工作就可以做到这一点,但如果您在运行时生成 JAR,打包代理所需的所有类可能会有点棘手。

我希望包含一个演示代理来演示在运行时附加分析器,但它最终太长而无法发布。尽管如此,我还是把它放在了 Github repo 中。 .

此方法的

一个警告 是它使您的程序依赖于 JDK 附带的 tools.jar,而 JRE 中不存在该 tools.jar。您可以通过将 tools.jar 与您的应用程序一起(或在其中提取)来解决此问题,但您仍然需要提供 Attach API 所需的 attach native 库你的申请。我已经在上面链接的存储库中包含了我可以找到的所有平台的库,尽管您也可以自己获取它们。

根据您的用例,这可能是理想的,也可能不是理想的。但它确实有效!


这在问题中并不清楚,但如果您希望在运行时使用您自己的类完全“热交换”一个类,则不需要使用任何字节码操作库。相反,您可以单独编译您的类(确保相同的包、类名等)并在目标上调用 transform 时简单地返回新类的字节类。

关于java - 在运行时替换某些方法的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11749409/

相关文章:

java - 有没有办法在 play 框架中的拦截器和 Action 之间共享数据?

scala - 如何在 Play Framework 中创建多个自定义字段?

php - 更好的站点性能 : multiple simple mySQL queries or one complex mySQL query later manipulated in PHP?

java - JSF持久性文件问题

java - 如何在Java中按行将CSV文件分割成不同的CSV文件?

java - 实例控制类和多线程

java - HikariCP 连接池未关闭

java - 算法运行时间分析

visual-studio-2010 - MS缺少VSTO 4.0 Runtime下载?

java - SWT 未启用 shell