我正在尝试编写一个通过 Attach api 动态加载的 Java 代理库,以重新转换某些方法(出现在某些线程的堆栈跟踪中的方法)以记录方法进入/退出。然后通过自定义 MBean
导出方法入口/导出信息。
只要检测的方法不是 native 的,我当前的“原型(prototype)”到目前为止就可以工作。
根据java.lang.instrument.Instrumentation#setNativeMethodPrefix()的文档,Java 代理应该可以用非 native stub 方法替换 native 方法,并添加另一个名称中带有该前缀的 native 方法,然后将其绑定(bind)到原始 native 方法的 native 代码。
但是,在实现此操作时,我收到此错误:
java.lang.UnsupportedOperationException: class redefinition failed: attempted to add a method
这是正确的,因为我添加了新的 native 方法。
仅用非 native 方法替换 native 方法才有效,但随后我无法将调用委托(delegate)回原始 native 方法。在另一个类中定义 native 方法不起作用,因为 native 方法是通过类名和方法名查找的,并且没有 nativeMethodClassSuffix
或类似的内容。在另一个新的类加载器中定义另一个同名的类是可行的,我认为可以通过一些间接方式将调用委托(delegate)给新类,但是一个 native 库只能链接到仅由一个类加载的 native 方法类加载器,因此我无法正确链接 native 方法。
我在这里遗漏了什么明显的东西吗?我的代码有点太长,无法在这里发布,如果有人认为它有帮助,我可以尝试构建一个小型 Java 代理示例来显示问题并在此处链接。
最佳答案
Is there anything obvious I'm missing here? My code is a bit too long to post here, if anyone thinks it helps I can try to build a small example java agent that shows the problem and link to it here.
没有。如果屏蔽掉 native 方法,则不再有任何方法可以从 JNI 调用它。您需要使用 native 代码调用该方法。 (我不知道那是什么,但如果不可能的话我会感到惊讶)
另一个选择是更改对 native 方法的所有引用,而不是将其屏蔽掉。这样,您仍然可以在选择时调用原始方法。
关于java - 重新转换 Java Instrumentation Agent 库中的 native 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13954192/