java - 使用 Java 代理修改已经加载的类?

标签 java bytecode javaagents jrebel

目前我正在尝试修改驻留在已由 JVM 加载的类 中的方法体。我知道 JVM 实际上不允许更改已经加载的类的定义。但是我的研究让我想到了 JRebel 或 Java Instrumentation API 等实现,它们都使用基于代理的方法。我知道如何在代表 Javassist 加载类之前立即执行此操作。但考虑到例如在应用程序启动时加载类定义的 EJB 环境中的 JRebel,难道不能在 JVM 加载的类上修改字节码吗?

最佳答案

好吧,你了解到 Instrumentation API存在并提供 redefinition of classes作为一个操作。因此,是时候重新考虑“JVM 实际上不允许更改已加载类的定义”的初始前提了。

你应该注意到

  • 如链接所示,Instrumentation API 是标准 API 的一部分
  • 然而,对类重新定义的支持是可选的。你可以ask当前JVM是否支持该特性
  • 可能仅限于不支持所有类;你可能会问whether it’s possible for a particular class
  • 即使支持,变化也可能有限,引用the documentation :

    The redefinition may change method bodies, the constant pool and attributes. The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance. These restrictions maybe be lifted in future versions.

  • 在你重定义的时候,可能有线程在执行这些类的方法代码;然后这些执行将使用旧代码完成


因此 Instrumentation 仅用于调试和分析等。

但其他框架,如 EJB 容器,在生产代码中提供类重新加载,通常求助于创建新的 ClassLoader s 创建不同版本的类,然后完全独立于旧版本。

在Java运行时环境中,类的标识由一对<ClassLoader, Qualified Name>组成。而不仅仅是一个合格的名字……

关于java - 使用 Java 代理修改已经加载的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29891221/

相关文章:

java - 拦截来自特定命名空间的所有方法/构造函数/getters/setters

java - LocalVariableTable 中缺少什么?

java - android 在运行时替换方法调用

java - 如何在不停止 JVM 的情况下将 Javaagent 添加到 JVM?

java - 如何获取 IntelliJ 的项目文件 View 以显示源文件夹中的包和目录?

java - Wro4j、webjars 和 font-awesome

Java 代理 : transform() not applied on all classes

java - 重新转换 Java Instrumentation Agent 库中的 native 方法

java servlet 查询,带有来自 html 表单的参数

java - 使用 JOptionPane 打印报告