作为检测工具套件的一部分,我们有一个静态的prepass,可以修改类的某些方法,然后使用用户定义的属性标记这些方法。运行应用程序时,如果将类文件直接呈现给transform()方法,即它是该类的第一个负载,则可以看到这些属性。但是,如果我使用retransformClasses(),那么当我在transform()方法中获得控制权时,我的属性已被删除。我可以看到为什么在重新创建要传递给transform()的类字节时JVM可能会丢弃未知属性的原因,但是我找不到任何证明和/或描述此行为的文档。
我如何实现这个目标?我无法保证RuntimeVisible批注不会发生同样的情况。而且即使保留它们,使用它们也比我要避免使用该方法的属性困难得多。
关于如何通过retransformClasses()保留的方法添加“注释”的任何想法?
谢谢您的建议。
一旦加载了类文件,HotSpot JVM不会保留原始字节码。而是在需要时从内部VM表示中reconstitutes字节码。 VM无法理解的属性无法恢复。
[documentation至retransformClasses
明确提到了这种可能性:
初始类文件字节代表传递给ClassLoader.defineClass或redefineClasses(任何转换之前被应用),但是它们可能不完全匹配。常数池可能没有相同的布局或内容。常量池可能有更多或更少的条目。常量池条目可能在不同的顺序;但是,常量池索引在以下字节码中方法将对应。某些属性可能不存在。哪里顺序没有意义,例如方法的顺序,顺序可能无法保留。
同时,JVM理解RuntimeVisibleAnnotations
属性。而且,有Java API可以访问它们,因此JVM不能在转换过程中丢弃它们。重构字节码时,HotSpot JVM确实为writes RuntimeVisibleAnnotations
。
因此,最好的选择是使用注释-毕竟,它们是专门为使用用户定义的元数据标记成员而设计的。