我一直在尝试使用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加载器的路径无关。
如果您对正在发生的事情有所了解,我会很高兴听到它!
答案 0 :(得分:1)
NoSuchMethodError
很可能不是因为没有向bootstrap类加载器添加内容而引起的。这可能是一个问题的唯一可能性是,如果突然有两个这样的罐子,其中一个是仪器化的,另一个不是。
如果您调用将方法checkFinite(D)V
更改为另一种方法checkFinite<new_descriptor>
,则需要确保使用FastMath.floor
的任何类将描述符更新为此方法。这意味着您需要遍历每个类的每个方法,以查找ASM的visitMethodIns
次调用。好像你错过了一些。由于您要更改FastMath
类的布局,因此必须在首次加载时对其进行检测,而您无法重新定义。
Java内部类不知道FastMath
,因为这是第三方依赖项。因此,应该可以检测代理商的任何电话。在我看来,你过早地加载FastMath
。