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

pkl*_*nst 4 java bytecode javaagents jrebel

目前我正在尝试修改驻留在JVM已经加载的类中的方法体.我知道JVM实际上不允许更改已经加载的类的定义.但是我的研究使我得到了像JRebel或Java Instrumentation API这样的实现,两者都使用了基于代理的方法.我知道如何在代表Javassist加载类之前做到这一点.但是考虑到在应用程序启动时加载类定义的EJB环境中的JRebel,不应该在加载JVM的类上进行字节码修改吗?

Hol*_*ger 6

好吧,您了解到Instrumentation API存在,它提供了类的重新定义作为操作.那么现在是时候重新考虑"JVM实际上不允许更改已经加载的类的定义"的初始前提.

你应该注意到这一点

  • 如链接所示,Instrumentation API是标准API的一部分
  • 然而,重新定义类的支持是可选的.您可能会询问当前的JVM是否支持此功能
  • 它可能仅限于不支持每个班级; 你可能会问一个特定的课程是否可能
  • 即使它受支持,更改也可能有限,引用文档:

    重新定义可以改变方法体,常量池和属性.重定义不得添加,删除或重命名字段或方法,更改方法的签名或更改继承.在将来的版本中可能会取消这些限制.

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


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

但是其他框架,比如EJB容器,在生产代码中提供类重新加载,通常需要创建新的ClassLoaders,它们创建不同版本的类,然后完全独立于旧版本.

在Java运行时环境中,类的标识由一对<ClassLoader, Qualified Name>而不仅仅是限定名称组成......