4

I have a java program that calls a native function many times over. My problem is that this function has a memory leak and everything that I do to get rid of it cause a memory dump. Any help would be greatly appreciated.

This is my code

JNIEXPORT void JNICALL Java_class_method_getInput
(JNIEnv *env, jobject obj)
{
    if (inputIsAvailable)
    {

    int size = getBufferCurrentIndex();
    size -= getBufferReadIndex();
    size *= 2;

    char *finalSendArray = new char[size];

    getCommand(finalSendArray);

    jbyteArray byteArray = env->NewByteArray(size / 2);
    env->SetByteArrayRegion(byteArray, 0, size / 2, (jbyte*) finalSendArray);

    while(methodID == 0)
    {
        jclass cls = env->GetObjectClass(obj);
        methodID = env->GetMethodID(cls, "setCommand", "([B)V" );
    }

    env->CallVoidMethod(obj, methodID, byteArray);

    //env->ReleaseByteArrayElements(byteArray, (jbyte*) finalSendArray, JNI_ABORT);

My problem is that the above ^ code causes a memory dump if it is uncommented, if it is not uncommented my program runs out of memory in minutes

    env->DeleteLocalRef(byteArray);
    delete[] finalSendArray;
    }
}

any help would be appreciated. Thanks!

Tyler Davis
  • 2,420
  • 2
  • 23
  • 19
  • Release the `byteArray` first, then delete the underlying memory? – Kerrek SB Sep 06 '13 at 23:44
  • Did my response solve your issue? Mark it as correct if it did. Why are you doing this all in C? What does getCommand do? Could it be done in java? jni is expensive. – JustinDanielson Sep 07 '13 at 10:30
  • @JustinDanielson hey sorry it took so long for a reply, I still have a leak somewhere. I'm not sure where. I'm using c++ because I am just reusing code that was already built. It could be re-written in Java but I would prefer just keeping it in it's current implementation. – Tyler Davis Sep 07 '13 at 15:31
  • @KerrekSB I wish that had worked... but it did not unfortunately. – Tyler Davis Sep 07 '13 at 15:33
  • Sorry to hear. I don't really know; the only advice I could give is to read the JNI spec carefully and make sure you understand all the different lifetimes and dependencies. – Kerrek SB Sep 07 '13 at 15:58
  • Did you solve the problem? What was causing it? I'm curious because I've been working with some JNI related stuff and run into strange things pretty often. – JustinDanielson Sep 13 '13 at 06:54
  • unfortunately I did not solve the problem / I could not find the problem. I ended up re-writing it in Java. Sorry, wish I had found it, but best of luck and thanks for your help! – Tyler Davis Sep 14 '13 at 17:57
  • That's not good Im finding the same problem here. – OnlyAngel Feb 07 '14 at 01:08

1 Answers1

4

ReleaseByteArrayElements will also free the memory if you use the JNI_ABORT param. So when you're doing the delete and release later on, one of those pointers is pointing to uninitialized memory which is causing the dump.

One of these will work, I fairly certain it is the first one that works.

env->ReleaseByteArrayElements(byteArray, (jbyte*) finalSendArray, JNI_ABORT);
delete[] finalSendArray;

Try this if the first fails.

env->ReleaseByteArrayElements(byteArray, (jbyte*) finalSendArray, JNI_ABORT);
env->DeleteLocalRef(byteArray);

Put a print statement after the ReleaseByteArrayElements, you will see that your program is executing beyond that command and crashing on the Release/Delete[]

Search for "Table 4-10 Primitive Array Release Modes"

JustinDanielson
  • 3,155
  • 1
  • 19
  • 26
  • the first one causes `code` *** glibc detected *** /usr/lib/jvm/java-7-openjdk-amd64/bin/java: double free or corruption (fasttop): 0x00007fb8a4001030 *** `code` the second one I still have a memory leak. I'm going to make sure that the memory leak is actually there – Tyler Davis Sep 07 '13 at 15:26
  • It could be in getCommand. Is it no longer crashing now in the same place? – JustinDanielson Sep 07 '13 at 21:27
  • The log files point to the function SetByteArrayRegion and it throws the error bad_alloc – Tyler Davis Sep 09 '13 at 15:05
  • Could either of your allocations be failing?(returning null). How much memory do you have allocated to the JVM? Check if either of those pointers are NULL before calling setByteArrayRegion. If they are, print something out, write to the log, or throw an exception. Is bad_alloc throwing on the first JNI call? or after a bunch?(mem leak) – JustinDanielson Sep 11 '13 at 00:12
  • It could be that you're running out of heap memory. Check out this to increase it, http://stackoverflow.com/questions/1565388/increase-heap-size-in-java – JustinDanielson Sep 11 '13 at 00:15