2012-12-19 18 views
1

我正在尝试编写一个通过attach api动态加载的Java代理库来重新转换某些方法(出现在某些线程的堆栈跟踪中)用于记录方法的进入/退出。然后通过自定义的MBean将方法输入/输出信息输出。重新转换Java Instrumentation代理库中的本地方法

我目前的“原型”迄今为止工作,只要仪器化的方法不是本地的。

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

然而,实现这个的时候,我得到这个错误:

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

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

只用非本地方法替换原生方法,但我无法将调用委托给原始本机方法。在另一个类中定义本地方法不起作用,因为本地方法是按类名称和方法名称查找的,并且没有nativeMethodClassSuffix或类似方法。在另一个新的类加载器中定义另一个具有相同名称的类将会工作,我认为可能有一些间接的方式将调用委托给新类,但是一个本地库只能链接到由仅有一个类加载的本地方法类加载器,所以我不会得到适当链接的本地方法。

有什么明显的我在这里失踪?我的代码有点太长,不能在这里发布,如果有人认为它有帮助,我可以尝试构建一个小的示例Java代理,显示问题并链接到这里。

+0

您是否找到解决问题的方法?我有类似的问题,我会很高兴看到一些参考代码。 – nadavy

+0

@nadavy不,我决定不使用原生方法并通过链接到这个StackOverflow问题来记录这个限制:) – mihi

+0

lol。那么,这是一个解决方案:-)。感谢您的回应! – nadavy

回答

2

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.

不可以。如果你掩盖了一个本地方法,那么就没有办法从JNI调用它了。您需要使用本地代码调用该方法。 (我不知道那是什么,但如果不可能,我会感到惊讶)

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

+0

感谢您的回答。我很困惑,因为本地方法前缀特征听起来像我应该使用的。更改所有对该方法的引用在我的情况下不可行,因为这需要扫描所有加载的类以供参考。感谢无论如何快速回应:) – mihi