2012-02-20 25 views
10

我有一個創建一個Java集合原生對象,然後將它們返回到Java以下JNI方法:JNI對象的創建和存儲管理

JNIEXPORT jobject JNICALL Java_com_test_myClass_myMethod(JNIEnv * env, jclass klass) { 
    jclass arrayClass = env->FindClass("java/util/ArrayList"); 
    jmethodID initMethod = env->GetMethodID(arrayClass, "<init>", "()V"); 
    jmethodID addMethod = env->GetMethodID(arrayClass, "add", "(Ljava/lang/Object;)Z"); 
    jobject myArray = env->NewObject(arrayClass, initMethod); 

    env->CallBooleanMethod(myArray, addMethod, env->NewStringUTF("Hello")); 
    env->CallBooleanMethod(myArray, addMethod, env->NewStringUTF("World")); 

    return myArray; 
} 

我需要釋放在本地代碼創建的對象,還是由GC自動完成? 如果我這樣做,我該如何做,因爲我需要將它返回給Java?

+0

我認爲這將取決於本機代碼做自己的內存管理。在這種情況下,我會想象你需要添加另一個本地方法來釋放分配的對象,當你完成它們時你手動調用它。更一般地說,如果你正在用JNI做事情,那麼我希望你已經準備好了一個受到傷害的世界。此答案可能有所幫助:http://stackoverflow.com/questions/214699/jni-memory-management-using-the-invocation-api – aroth 2012-02-20 23:34:24

+3

@aroth - 錯誤。如果您在JNI中分配Java對象,則它們是由GC擁有的Java對象。 – bmargulies 2012-02-20 23:38:32

+0

@bmargulies - 有道理,但在通過調用'malloc()'來分配非Java對象/內存的本地代碼的情況下呢? – aroth 2012-02-20 23:50:18

回答

11

您不需要釋放在本機代碼中創建的Java對象。事實上,你不能。垃圾收集器可以在沒有進一步引用時釋放對象。

有時,在本機代碼中將引用釋放到Java對象是有用的。這可以減少本機代碼持有時的內存需求,但不再需要對大對象或大量引用的引用。

來自:「全球和本地參考」中的JNI specification

在大多數情況下,程序員應該依靠VM在本地方法返回後釋放所有本地引用。但是,有時程序員應該明確地釋放本地引用。例如,考慮以下情況:

  • 本機方法訪問大型Java對象,從而創建對Java對象的本地引用。本地方法然後在返回給調用者之前執行額外的計算。對大型Java對象的本地引用將防止對象被垃圾收集,即使該對象不再用於其餘計算。
  • 本地方法創建大量本地引用,儘管並非所有引用都同時使用。由於VM需要一定的空間來跟蹤本地引用,因此創建過多的本地引用可能會導致系統內存不足。例如,本地方法遍歷大量對象,檢索元素作爲本地引用,並在每次迭代時對一個元素進行操作。每次迭代後,程序員不再需要本地引用數組元素。

其他細節被提供 見"Freeing References"的JNI程序員指南中。

+0

我閱讀了有關釋放引用的指南,但對此有疑問:可能在我的初始文章中調用該方法很多次會造成資源耗盡問題?如果是的話,我可以在哪裏免費的參考,因爲我仍然需要返回它們? – nbarraille 2012-02-21 00:05:51

+0

每次調用後都會自動釋放本地引用。除非1)您創建了全局引用,或者2)需要在調用完成之前釋放本地引用,否則不必明確地執行此操作,原因如鏈接中所述。您正在返回的參考正在被複制。myArray和返回的參考指向同一個Java對象。 – 2012-02-21 14:07:57

+0

鏈接是死的... – BeniBela 2013-04-30 00:05:49

相關問題