2011-12-20 14 views
10

Ho un metodo Java che elabora una bitmap e restituisce una stringa. Quando chiamo questo metodo da JNI (VS 2010) funziona, ma se chiamo questo metodo molte volte, la memoria del processo cresciuta fino all'arresto. L'istruzione che utilizzano molta memoria è:Perdita di memoria JNI NewByteArray

jbyteArray jBuff = _env->NewByteArray(b->Length); 

Il mio codice:

static jobject staticArray=0; 

System::String^ MyClass::ExecuteJavaMethod(System::Drawing::Bitmap^ bmp) 
{ 
    JNIEnv *_env; 
    System::String^ out; 
    unsigned const char * buff; 

    int res = jvm->AttachCurrentThread((void **)&_env, NULL); 

    if (jvm->GetEnv((void**) &_env, JNI_VERSION_1_6) != JNI_OK) 
    { 
     return "GetEnv ERROR"; 
    } 

    //save the bitmap in the stream 
    MemoryStream^ ms = gcnew MemoryStream(); 
    bmp->Save(ms, ImageFormat::Bmp); 

    //get the bitmap buffer 
    array<unsigned char>^b = ms->GetBuffer() ; 

    //unmanaged conversion 
    buff = GetUnmanaged(b,b->Length); 


    //fill the buffer 
    jbyteArray jBuff = _env->NewByteArray(b->Length);  
    _env->SetByteArrayRegion(jBuff, 0, b->Length, (jbyte*) buff); 

    //call the java method 
    jstring str = (jstring) _env->CallStaticObjectMethod ( Main, 
           javaMethod, 
           jBuff); 



    // _env->ReleaseByteArrayElements(jBuff,(jbyte*)buff), 0); //NOT WORKING 

    //staticArray= _env->NewGlobalRef(jBuff); NOT 
    //_env->DeleteLocalRef(jBuff);    WORKING 


    //return the string result of the java method 
    return gcnew String(env->GetStringUTFChars(str, 0)); 

} 
+0

Perché si commenta la linea che fa '_ReleaseByteArrayElements()'? – fge

+0

perché è lo stesso, la memoria sale e va in crash ... – Riccardo

+0

Sembra che tu non stia rilasciando il 'buff' in nessun punto. 'GetUnmanaged' alloca un buffer temporaneo che non viene mai recuperato? –

risposta

17

la risposta è: _env->DeleteLocalRef(jBuff);

0

non hai chiamato DetachCurrentThread() per ogni AttachCurrentThread(), che vengono richieste in Java Native Interface Specification. Ciò rende i riferimenti locali (jBuff e str) impossibili da liberare automaticamente. Inoltre, è necessario rilasciare lo const char* tramite GetStringUTFChars().

Il modo corretto è il cambiamento

return gcnew String(env->GetStringUTFChars(str, 0)); 

in

const char* cstr = env->GetStringUTFChars(str, 0); 
System::String^ retstr = gcnew String(cstr); 
env->ReleaseStringUTFChars(str, cstr); 
jvm->DetachCurrentThread(); 
return retstr;