2011-08-16 38 views
9

看一看JNI的文檔在這裏:http://download.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.htmlJNI EnsureLocalCapacity - 爲什麼?

具體來說,看看什麼是對EnsureLocalCapacity功能描述說:

爲了向後兼容,虛擬機分配超出 在確保本地引用容量。 (作爲調試支持,虛擬機可能會給 用戶發出警告,說明正在創建太多本地引用。在 JDK中,程序員可以提供-verbose:jni命令行選項,以打開這些消息,以打開 。)VM調用FatalError如果沒有更多的本地 引用可以創建超出保證的容量。

此外,看看PushLocalFrame如何採取「容量」的參數。 (順便說一下,它沒有提到這是一個硬限制還是像EnsureLocalCapacity那樣的軟限制)。

究竟這些廢話是關於本地參考容量的呢?這些文檔說,虛擬機將願意分配超過當前正式容量的引用,那麼爲什麼它不這樣做,並保持所有這些容量凌亂的API?

爲了給C一個類比,感覺就像我被要求預先計劃多少次malloc()調用一樣,並且感覺有點荒謬。

有什麼重要的我只是沒有看到這裏?

回答

0

這是我的猜想。我懷疑增長的本地引用容量是很昂貴的,並且這個函數允許每個本地方法調用請求一次期望的容量。我認爲這更多的是關於性能而不是正確性。

0

據我瞭解,本地參考表的大小是預定義的,如果你分配的比它多,它只會崩潰。所以並不是虛擬機會永遠給你更多的本地參考。我在Android上使用JNI時遇到過這麼多次。通常很難找到這樣的內存泄漏。每次你使用JNI本地引用做一些事情時,調用env-> DeleteLocalRef()就會使代碼混亂。因此,不要用DeleteLocalRef()調用混淆代碼,我們可以確保我們不會創建太多引用並保持代碼非常乾淨。即使我們打算分配更多的本地引用,我們仍然可以調用PushLocalFrame()/ PopLocalFrame()並避免多次調用DeleteLocalRef()。

所以爲了給你比喻「C」,你需要預先計劃你的malloc調用,以避免所有必要的調用free()在最後。

0

JNI文檔在這個主題上很炫。我在實踐中發現,有時候本地引用的數量似乎是無限的,但是您真的可以用完本地引用,例如使用JNI調用遍歷數組時。什麼是本地參考?這是一個jobject(或jarray,的jstring,等等),你從任何這些來源獲得:

  • 從原始JNI調用返回像NewObjectV的()或GetObjectArrayElement()的方法調用返回像
  • CallObjectMethodV()
  • 傳遞給你的本地函數作爲參數
  • 也許別人我忘了

這些,你平時不用擔心傳遞給你的方法AR引用除非你打算將引用保留在當前方法調用之外,在這種情況下,你應該將其轉換爲全局方法。

值得注意的是,您不能掛在當前方法範圍之外的本地引用上。如果您打算將它存儲在C++對象中,則必須將其轉換爲全局對象。本地參考具有兩個優點

  1. 它們總是在當前幀超出範圍時自動釋放。
  2. 他們比轉換成全球

最喜歡的JNI錯誤更快,引用任何濫用是可怕的診斷,所以你真的不想買一個。你最好的防守是一致的方法。根據我的經驗,轉換本地到全球的成本相當小。除非你有非常嚴格的性能需求,否則我會提出以下建議。
鑑於此,我的原則是 - 永遠地方裁判轉換爲全局裁判,使用如下代碼:

jobject localjo = ... 
jobject globaljo = env->NewGlobalRef(localjo); 
env->DeleteLocalRef(localjo); 

在這一點上,你可以知道每一個裁判是全球性的,當你完成,你需要要記住每個環境都要執行env-> DeleteGlobalRef(globaljo)。在C++中,可以在JNI引用中編寫一個包裝類,它在dtor中調用env-> DeleteGlobalRef()。但是由於JNI沒有引用 - 爲你計算JNI引用,你可能還需要構建它。

相關問題