2

我正在尝试编写一个通过附加 api 动态加载的 Java 代理库,以重新转换一些方法(那些出现在某些线程的堆栈跟踪中的方法)以记录方法的进入/退出。然后通过自定义导出方法进入/退出信息MBean

到目前为止,只要检测方法不是本地的,我当前的“原型”就可以工作。

根据java.lang.instrument.Instrumentation#setNativeMethodPrefix()的文档,java 代理应该可以用非本地存根方法替换本地方法,并在其名称中添加另一个带有该前缀的本地方法,然后绑定到原始本机方法的本机代码。

但是,在实施此操作时,我收到此错误:

java.lang.UnsupportedOperationException: class redefinition failed: attempted to add a method

这是正确的,因为我添加了新的本机方法。

只有用非本地方法替换本地方法才有效,但是我不能将调用委托回原始本地方法。在另一个类中定义本机方法也不起作用,因为本机方法是通过类名和方法名查找的,没有nativeMethodClassSuffix或类似的。在另一个新的类加载器中定义另一个同名的类是可行的,我认为可以通过一些间接方式将调用委托给新类,但是一个本机库只能链接到由只有一个类加载的本机方法类加载器,所以我不会正确链接本机方法。

我在这里有什么明显的遗漏吗?我的代码有点长,无法在此处发布,如果有人认为它有帮助,我可以尝试构建一个小型示例 java 代理来显示问题并在此处链接到它。

4

1 回答 1

2

我在这里有什么明显的遗漏吗?我的代码有点长,无法在此处发布,如果有人认为它有帮助,我可以尝试构建一个小型示例 java 代理来显示问题并在此处链接到它。

不,如果您屏蔽了本机方法,则不再有任何方法可以从 JNI 调用它。您需要使用本机代码调用该方法。(我不知道那是什么,但如果不可能,我会感到惊讶)

另一种选择是更改对本机方法的所有引用,而不是将其屏蔽掉。这样,您仍然可以在选择时调用原始方法。

于 2012-12-19T14:27:22.420 回答