2011-12-20 20 views
10

Tengo un método de Java que procesa un mapa de bits y devuelve un String. Cuando llamo a este método desde JNI (VS 2010) funciona, pero si llamo a este método muchas veces, la memoria del proceso creció hasta el bloqueo. La instrucción que utilizan una gran cantidad de memoria es:JNI NewByteArray memory leak

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

Mi código:

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

¿Por qué te comentan su línea que hace '_ReleaseByteArrayElements()'? – fge

+0

porque es lo mismo, la memoria sube y se cuelga ... – Riccardo

+0

Parece que no estás liberando 'buff' en ningún momento. ¿'GetUnmanaged' asigna un buffer temporal que nunca se recupera? –

Respuesta

17

la respuesta es: _env->DeleteLocalRef(jBuff);

0

no llamó DetachCurrentThread() para cada AttachCurrentThread(), que se solicita en Java Native Interface Specification. Eso hace que las referencias locales (jBuff y str) no se puedan liberar automáticamente. Además, es necesario liberar el const char* obtenido a través de GetStringUTFChars().

La forma correcta es cambiar

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

en

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