2012-12-19 44 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