2011-03-16 4 views
5

Je suis débutant en Java. Mon problème est: J'appelle la méthode d'une classe Java de C++. Pour cela, j'utilise JNI. Everythings fonctionne correctement, mais j'ai quelques Fuites de mémoire dans le processus de C++ programme ...Java JNI fuite dans le processus C++

.. Alors je l'ai fait exemple simple ..

1) Je crée une machine java (JINT res = JNI_CreateJavaVM (& JVM (void **) & env, & vm_args);)

2) puis-je prendre un pointeur sur la classe Java (JClass cls = env-> FindClass ("test_jni"));

3) après que je crée un objet de l'objet de classe Java, en appelant le constructeur (testJavaObject = env-> NewObject (cls, testConstruct);)

à ce moment dans le processus de programme C++ est alloué 10 Mo de mémoire

4) Ensuite je supprimer la classe, l'objet et la machine Java ..

en ce moment les 10 Mo de mémoire ne sont pas libres ........ ......... Donc, ci-dessous j'ai quelques lignes de code

C++ programme

void main() 
{ 
    { 
     //Env 
     JNIEnv *env; 
     // java virtual machine 
     JavaVM *jvm; 
     JavaVMOption* options = new JavaVMOption[1]; 
     //class paths 
     options[0].optionString = "-Djava.class.path=C:/Sun/SDK/jdk/lib;D:/jms_test/java_jni_leak;"; 
     // other options 
     JavaVMInitArgs vm_args; 
     vm_args.version = JNI_VERSION_1_6; 
     vm_args.options = options; 
     vm_args.nOptions = 1; 
     vm_args.ignoreUnrecognized = false; 
     // alloc part of memory (for test) before CreateJavaVM 
     char* testMem0 = new char[1000]; 
     for(int i = 0; i < 1000; ++i) 
      testMem0[i] = 'a'; 
     // create java VM 
     jint res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); 
     // alloc part of memory (for test) after CreateJavaVM 
     char* testMem1 = new char[1000]; 
     for(int i = 0; i < 1000; ++i) 
      testMem1[i] = 'b'; 
     //Creating java virtual machine 
     jclass cls = env->FindClass("test_jni"); 
     // Id of a class constructor 
     jmethodID testConstruct = env->GetMethodID(cls, "<init>", "()V"); 
     // The Java Object 
     // Calling the constructor, is allocated 10 MB of memory in c++ process 
     jobject testJavaObject = env->NewObject(cls, testConstruct); 
     // function DeleteLocalRef, 
     // In this very moment memory not free 
     env->DeleteLocalRef(testJavaObject); 
     env->DeleteLocalRef(cls); 
     // 1!!!!!!!!!!!!! 
     res = jvm->DestroyJavaVM(); 
     delete[] testMem0; 
     delete[] testMem1; 
     // In this very moment memory not free. TO /// 
    } 
    int gg = 0; 
} 

classe java (il Alloue juste un peu de mémoire)

import java.util.*; 

public class test_jni 
{ 
    ArrayList<String> testStringList; 
    test_jni() 
    { 
    System.out.println("start constructor"); 
    testStringList = new ArrayList<String>(); 
    for(int i = 0; i < 1000000; ++i) 
    { 
     // засераю память 
     testStringList.add("TEEEEEEEEEEEEEEEEST"); 
    } 
    } 
} 

vue mémoire du processus, après la mise en caisse javavm et objet java: testMem0 et testMem1 - Test de mémoire, c'est alloué par C++ .

************** 
testMem0 
************** 




JNI_CreateJavaVM 




************** 
testMem1 
************** 

// create java object 
jobject testJavaObject = env->NewObject(cls, testConstruct); 

************** 
vue en mémoire du processus

, détruire après JavaVM et supprimer ref sur l'objet Java: testMem0 et testMem1 sont supprimés à;

************** 




JNI_CreateJavaVM 




************** 

// create java object 
    jobject testJavaObject = env->NewObject(cls, testConstruct); 

************** 

Alors testMem0 et testMem1 est supprimé, mais JavaVM et objet Java ne ....

Sow ce que je fais mal ... et comment je peux libérer de la mémoire dans le C++ programme de processus.

QUELQUES EDIT ....

si j'alloc nouvelle mémoire (char * test3 = new char [1000]), après avoir détruit JVM, tas de C++ processus ressemble donc aime:

et la mémoire le processus grandit! ...

************** 




JNI_CreateJavaVM (memory after JVM) 




************** 

jobject testJavaObject = env->NewObject(cls, testConstruct); 
memory after Java object 


************** 

char* test3 (memory is allocated by char* test3 = new char[1000]) 

************** 
+0

Juste curieux: comment vérifiez-vous la mémoire libre? – bestsss

+0

je regarde la taille de la mémoire dans le gestionnaire de tâches et je regarde la mémoire dans heapviewer – DimShust

+0

dans ce cas, je considère comme un comportement normal; cela arrivera w/toute autre bibliothèque que vous ajoutez.Outre le tas, il y a du code à charger. Juste b/c il n'y a pas d'instances, cela ne signifie pas que le code entier va bouffer. La fuite serait si la mémoire continue à augmenter pour chaque alloc/dealloc d'une machine virtuelle. – bestsss

Répondre

3

Ceci est un comportement normal. La mémoire sera réutilisée si vous effectuez d'autres allocations dans votre processus, mais elle n'est pas retournée en tant que mémoire libre au système d'exploitation pour des raisons de performances. Vous n'avez pas de fuite de mémoire car cette mémoire n'est pas perdue, mais elle ne peut être réutilisée que par votre processus (jusqu'à ce qu'elle se termine bien sûr).

+0

J'ai fait quelques éditions du premier post, donc si j'alloue de la mémoire, après la destruction de VM Java, la mémoire du processus grandit ... – DimShust