Java代理:transform()未应用于所有类

时间:2015-12-15 09:49:30

标签: java javaagents

我一直在尝试使用Java代理程序对ASM应用字节码转换。

我使用premain方法实现了一个代理,为Instrumentation添加了一个转换器。 我添加了" Premain-Class" .jar清单中的行

Premain-Class: <MyAgentPath>

然后我尝试使用代理运行应用程序。

我遇到了一个问题:我的变换器修改了一些方法调用,因此如果不是所有涉及的类都被修改,它也无法工作。并且有一些类没有被修改,例如&#34; org.apache.commons.math3.util.FastMath&#34;。 当然,我收到了错误:

java.lang.NoSuchMethodError: org.apache.commons.math3.util.FastMath.floor<new_descriptor>

我查了很多帖子说它可能是引导加载程序,它不知道这个类的路径所以我试着用不同的方式添加它:

  • 添加&#34; Boot-Class-Path&#34;行到清单:

    Boot-Class-Path: <...>/commons-math3<...>.jar
    
  • 使用方法&#34; appendToBootstrapClassLoaderSearch(JarFile)&#34;

    inst.appendToBootstrapClassLoaderSearch("<...>/commons-math3<...>.jar");
    
  • 使用JVM参数&#34; -Xbootclasspath / a:&#34;

    -Xbootclasspath/a:<...>/commons-math3<...>.jar
    

这些都没有改变任何事情。

我还使用了Instrumentation类方法getAllLoadedClasses()来查看加载了哪些类,以及加载的应用程序进程中涉及的所有类,包括FastMath。

for(Class<?> clazz : MyAgent.getInstInstance().getAllLoadedClasses()){
    buffWrite.write(clazz.getName());

作为课程&#34; FastMath&#34;给出了一个错误,并且由于Bootstrap Loader应该有它的路径,我尝试在同一个包中的其他类中添加一些方法调用。似乎问题没有针对包的每个类显示。

例如:转换MathUtils并调用修改后的方法checkFinite(D)V - &gt; checkFinite<new_descriptor>

所以我猜这个问题与提供给bootstrap加载器的路径无关。

如果您对正在发生的事情有所了解,我会很高兴听到它!

1 个答案:

答案 0 :(得分:1)

NoSuchMethodError很可能不是因为没有向bootstrap类加载器添加内容而引起的。这可能是一个问题的唯一可能性是,如果突然有两个这样的罐子,其中一个是仪器化的,另一个不是。

如果您调用将方法checkFinite(D)V更改为另一种方法checkFinite<new_descriptor>,则需要确保使用FastMath.floor的任何类将描述符更新为此方法。这意味着您需要遍历每个类的每个方法,以查找ASM的visitMethodIns次调用。好像你错过了一些。由于您要更改FastMath类的布局,因此必须在首次加载时对其进行检测,而您无法重新定义

Java内部类不知道FastMath,因为这是第三方依赖项。因此,应该可以检测代理商的任何电话。在我看来,你过早地加载FastMath