5
votes

I am beginner in Java. My problem is: I am calling a Java class's method from c++. For this i am using JNI. Everythings works correct, but i have some memory LEAKS in the process of c++ program...

So.. i did simple example..

1) I create a java machine (jint res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);)

2) then i take a pointer on java class (jclass cls = env->FindClass("test_jni"));

3) after that i create a java class object object, by calling the constructor (testJavaObject = env->NewObject(cls, testConstruct);)

AT THIS very moment in the process of c++ program is allocated 10 MB of memory

4) Next i delete the class , the object, and the Java Machine ..

AT THIS very moment the 10 MB of memory are not free ................. So below i have a few lines of code

c++ program

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;
}

java class (it just allocs some memory)

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");
    }
  }
}

process memory view, after crating javaVM and java object: testMem0 and testMem1 - test memory, that's allocated by c++.

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




JNI_CreateJavaVM




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

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

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

process memory view, after destroy javaVM and delete ref on java object: testMem0 and testMem1 are deleted to;

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




JNI_CreateJavaVM




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

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

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

So testMem0 and testMem1 is deleted, But JavaVM and Java object not....

Sow what i do wrong... and how i can free memory in the c++ process program.

SOME EDIT....

if i alloc new memory (char* test3 = new char[1000]), after destroying JVM, heap of c++ process looks likes so:

And memory of process is growing up !...

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




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])

**************
1
Just curious: how do you check the free memory?bestsss
i look on memory size in task manager and i look on memory in heapviewerBoberCoder
in that case I consider it normal behavior; it will happen w/ any other library you add. Besides the heap, there is code to be loaded. Just b/c there are no instances, it doesn't mean the entire code is going puff. The leak would be if the memory keep rising for each alloc/dealloc of a virtual machine.bestsss

1 Answers

4
votes

This is normal behaviour. The memory will be reused if you do some other allocations in your process, but it is not returned as free memory to the OS for performance reasons. You don't have a memory leak as this memory is not lost, but it can only be reused by your process (until it exits of course).