Search code examples
androidjava-native-interface

Bad management memory Android with JNI


I am making an Android app, which when run for a long time crashes. I think that is for bad management of memory but I don't know how to solve it.

While the app runs this warning appears in logcat:

02-04 12:35:28.763: W/dalvikvm(12542): JNI: pin count on array 0x4278f710 ([B) is now 11

which increase continuously, and when the app crashes:

02-04 12:42:58.923: W/dalvikvm(12542): ReferenceTable overflow (max=1024)
02-04 12:42:58.923: W/dalvikvm(12542): JNI pinned array reference table (0x7f245198) dump:
02-04 12:42:58.923: W/dalvikvm(12542):   Last 10 entries (of 1024):
02-04 12:42:58.923: W/dalvikvm(12542):      1023: 0x4281b448 double[] (56 elements)
02-04 12:42:58.923: W/dalvikvm(12542):      1022: 0x427b9110 byte[] (17816 elements)
02-04 12:42:58.923: W/dalvikvm(12542):      1021: 0x427e9120 double[] (56 elements)
02-04 12:42:58.923: W/dalvikvm(12542):      1020: 0x427b9110 byte[] (17816 elements)
02-04 12:42:58.923: W/dalvikvm(12542):      1019: 0x427bf0d8 double[] (56 elements)
02-04 12:42:58.923: W/dalvikvm(12542):      1018: 0x427b9110 byte[] (17816 elements)
02-04 12:42:58.923: W/dalvikvm(12542):      1017: 0x427b87c0 double[] (56 elements)
02-04 12:42:58.923: W/dalvikvm(12542):      1016: 0x427b9110 byte[] (17816 elements)
02-04 12:42:58.923: W/dalvikvm(12542):      1015: 0x427aaca0 double[] (56 elements)
02-04 12:42:58.923: W/dalvikvm(12542):      1014: 0x427b9110 byte[] (17816 elements)
02-04 12:42:58.923: W/dalvikvm(12542):   Summary:
02-04 12:42:58.923: W/dalvikvm(12542):       512 of byte[] (17816 elements) (2 unique instances)
02-04 12:42:58.923: W/dalvikvm(12542):       512 of double[] (56 elements) (512 unique instances)
02-04 12:42:58.923: E/dalvikvm(12542): Failed adding to JNI pinned array ref table (1024 entries)
02-04 12:42:58.923: I/dalvikvm(12542): "main" prio=5 tid=1 RUNNABLE
02-04 12:42:58.923: I/dalvikvm(12542):   | group="main" sCount=0 dsCount=0 obj=0x415c3ca8 self=0x414fd408
02-04 12:42:58.923: I/dalvikvm(12542):   | sysTid=12542 nice=0 sched=0/0 cgrp=apps handle=1074508116
02-04 12:42:58.923: I/dalvikvm(12542):   | state=R schedstat=( 5061892458 1461440172 15878 ) utm=382 stm=124 core=0
02-04 12:42:58.923: I/dalvikvm(12542):   at android.graphics.Paint.native_getTextRunAdvances(Native Method)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.graphics.Paint.getTextRunAdvances(Paint.java:1973)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.graphics.Paint.getTextRunAdvances(Paint.java:1883)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.text.TextLine.handleText(TextLine.java:747)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.text.TextLine.handleRun(TextLine.java:898)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.text.TextLine.measureRun(TextLine.java:414)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.text.TextLine.measure(TextLine.java:293)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.text.TextLine.metrics(TextLine.java:267)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.text.BoringLayout.isBoring(BoringLayout.java:308)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.widget.TextView.onMeasure(TextView.java:6306)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.View.measure(View.java:16497)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.widget.LinearLayout.measureHorizontal(LinearLayout.java:1052)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.widget.LinearLayout.onMeasure(LinearLayout.java:590)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.View.measure(View.java:16497)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.widget.TableLayout.measureChildBeforeLayout(TableLayout.java:464)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.widget.TableLayout.measureVertical(TableLayout.java:476)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.widget.TableLayout.onMeasure(TableLayout.java:439)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.View.measure(View.java:16497)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.View.measure(View.java:16497)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.View.measure(View.java:16497)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
02-04 12:42:58.923: I/dalvikvm(12542):   at com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:327)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.View.measure(View.java:16497)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
02-04 12:42:58.923: I/dalvikvm(12542):   at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2291)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.View.measure(View.java:16497)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1916)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1113)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1295)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5670)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.Choreographer.doCallbacks(Choreographer.java:574)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.Choreographer.doFrame(Choreographer.java:544)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.os.Handler.handleCallback(Handler.java:733)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.os.Handler.dispatchMessage(Handler.java:95)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.os.Looper.loop(Looper.java:136)
02-04 12:42:58.923: I/dalvikvm(12542):   at android.app.ActivityThread.main(ActivityThread.java:5017)
02-04 12:42:58.923: I/dalvikvm(12542):   at java.lang.reflect.Method.invokeNative(Native Method)
02-04 12:42:58.923: I/dalvikvm(12542):   at java.lang.reflect.Method.invoke(Method.java:515)
02-04 12:42:58.923: I/dalvikvm(12542):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
02-04 12:42:58.923: I/dalvikvm(12542):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
02-04 12:42:58.923: I/dalvikvm(12542):   at dalvik.system.NativeStart.main(Native Method)
02-04 12:42:58.923: E/dalvikvm(12542): VM aborting
02-04 12:42:58.933: A/libc(12542): Fatal signal 6 (SIGABRT) at 0x000030fe (code=-6), thread 12542 (oleaudiocapture)

Finally my main native code is:

JNIEXPORT jdoubleArray JNICALL Java_com_sistoleaudiocapture_Processing_prueba_1nativa(
        JNIEnv * env, jclass, jlong retorno, jbyteArray data, jint lenbytes,
        jint frec) {

    jbyte *auxi = (env)->GetByteArrayElements(data, 0);
    int16_t *aux = (int16_t*) auxi;
    int16_t * newsignal;
    jdoubleArray ret = env->NewDoubleArray(8 * 7);
    double *d_est = env->GetDoubleArrayElements(ret, JNI_FALSE);
    double *ToF_est;
    double ToF_c[4];
    double *coor;

    ((Parameters*) retorno)->fs = frec;
    ((Parameters*) retorno)->t_samp = (double) 1 / frec;


    newsignal = ((Parameters*) retorno)->preobject.PreProcess(aux, lenbytes,
            ((Parameters*) retorno)->t_max, ((Parameters*) retorno)->t_samp,
            ((Parameters*) retorno)->dur_trig,
            &((Parameters*) retorno)->ToFobject);


    ToF_est = ((Parameters*) retorno)->ToFobject.CalcToF(newsignal,
            ((Parameters*) retorno)->fs);


    for (int i = 0; i < 4; i++) {
        ToF_c[i] = ToF_est[i] - ((Parameters*) retorno)->t_excel[i]
                - ((Parameters*) retorno)->t_comp[i];
        d_est[i] = ToF_c[i] * ((Parameters*) retorno)->v;
    }


    ((Parameters*) retorno)->pos_rx_est =
            ((Parameters*) retorno)->triobject.calc_trilateracion(d_est,
                    ((Parameters*) retorno)->pos_rx_track);


    coor = ((Parameters*) retorno)->trackobject.track(
            ((Parameters*) retorno)->pos_track,
            ((Parameters*) retorno)->pos_rx_track,
            ((Parameters*) retorno)->pos_rx_est);

    d_est[4] = coor[0];
    d_est[5] = coor[1];
    d_est[6] = coor[2];




    return (ret);

}

I suppose that is for some pointer or something like that.
Help?


Solution

  • Yes, you definitely have a leak here. It's not a classical memory leak, but an overflow of one of the tables that JNI uses to keep the references. Most likely, there is no memory leak, and the multiple references to byte[17816] all point to the same object. I hope that your Java code somewhere releases the double[56] arrays that are returned by your native method.

    The table overflows because you never call ReleaseByteArrayElements() and ReleaseDoubleArrayElements(). You should call the appropriate JNI function as soon as possible after the "pinned" data (the pointer acquired from GetByteArrayElements() or GetDoubleArrayElements()) is not needed anymore.

    In your case, env->ReleaseDoubleArrayElements(ret, d_est, 0) should be called just before return;, and env->ReleaseByteArrayElements(data, auxi, JNI_ABORT) after call to preobject.PreProcess().