user3243651
user3243651

Reputation: 241

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?

Upvotes: 0

Views: 2022

Answers (2)

Alex Cohn
Alex Cohn

Reputation: 57183

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().

Upvotes: 1

mbrenon
mbrenon

Reputation: 4941

You must call Release<PrimitiveType>ArrayElements after each call to Get<PrimitiveType>ArrayElements, as soon as you don't need to manipulate the array in native code anymore.

Otherwise, a reference is kept on the Java arrays forever... until you fill the maximum number of possible references (1024 in this case), which causes your crash.

Long story short, at the end of your native function, you should add something like:

env->ReleaseDoubleArrayElements(ret, d_est, FLAG);
env->ReleaseByteArrayElements(data, auxi, FLAG);

With FLAG being either 0, JNI_ABORT or JNI_COMMIT. Have a look at the JNI documentation for more details!

Upvotes: 3

Related Questions