user2783377
user2783377

Reputation: 31

JNI reporting Invalid indirect reference on GetByteArrayElements in Android

I have an issue. I'm calling a test function that gets a number of bytes from a Java import function and then returns that data as an array of shorts. At the moment I'm getting a problem that the program crashes with indirect reference. My code is this:

#define AR_LEN  8
JNIEXPORT jshortArray JNICALL Java_com_example_datafeed_DataFeed_decode
    (JNIEnv *env, jobject obj) {
    int out_size = 0;
    int i, frame_count;
    short  *data;          /* data stream               */
    int shutdown = 1;
    jbyte *temp;
    short data_btes = AR_LEN *2;
    jshortArray j_out_data;

   // This gets the java class references
    jclass cls = (*env)->FindClass(env, "com/example/datafeed/DataFeed");
    jmethodID getbytes = (*env)->GetMethodID(env, cls, "getBytes", "(I)[B");
    jmethodID outputMethod = (*env)->GetMethodID(env, cls, "playData", "([S)V");
   // Set up a return array
    j_out_data = (*env)->NewShortArray(env, AR_LEN);
    data = malloc(AR_LEN * 2 + 2);
    while(shutdown != 0) {
        __android_log_print(ANDROID_LOG_ERROR, "Native", "Calling Method %d", data_btes);
        // Call the java method to return byte array
        jbyteArray getbytes_ret = (*env)->CallObjectMethod(env, obj, getbytes, data_btes);
        // check for returned data
        __android_log_print(ANDROID_LOG_ERROR, "Native", "Returned %p %d", temp, getbytes_ret);

       //Get the array elements.  This line seems to crash
        temp = (*env)->GetByteArrayElements(env, getbytes_ret, 0);

        __android_log_print(ANDROID_LOG_ERROR, "Native", "Array Set");
        memcpy(data, temp, data_btes);
        __android_log_print(ANDROID_LOG_ERROR, "Native", "Memory Copied");
       // Delete the referece to temp
        (* env)->DeleteLocalRef(env,temp);
        if(temp == NULL)  {
            shutdown = 0;
        } else {
           // Set the Array of shorts

            (*env)->SetShortArrayRegion(env,j_out_data, 0, AR_LEN, data);
    // Call the return method
         (*env)->CallObjectMethod(env, obj, outputMethod, j_out_data);
      }
    }

    (* env)->DeleteLocalRef(env,outputMethod);
    (* env)->DeleteLocalRef(env,j_out_data);

 }

When I run this code I get this output:

E/Native(18292): Calling Method 16
D/FEED(18292): getting 16 bytes
D/FEED(18292): returning 16 bytes  
E/Native(18292): Returned 
E/Native(18292): Array Set
E/Native(18292): Memory Copied
W/dalvikvm(18292): JNI WARNING: DeleteLocalRef(0x42e06ac0) failed to find entry
D/OUTPUT(18292): recieved 8 data
E/Native(18292): Calling Method 0x6ded7770 16
E/Native(18292): Returned 
W/dalvikvm(18292): Invalid indirect reference 0x8 in decodeIndirectRef
I/dalvikvm(18292): "Thread-55890" prio=5 tid=11 RUNNABLE
I/dalvikvm(18292):   | group="main" sCount=0 dsCount=0 obj=0x42e06520 self=0x75221628
I/dalvikvm(18292):   | sysTid=18308 nice=0 sched=0/0 cgrp=apps handle=1965187080
I/dalvikvm(18292):   | state=R schedstat=( 0 0 0 ) utm=0 stm=0 core=0
I/dalvikvm(18292):   at com.example.datafeed.DataFeed.decode(Native Method)
I/dalvikvm(18292):   at com.example.datafeed.DataFeed.run(DataFeed.java:68)
I/dalvikvm(18292):   at java.lang.Thread.run(Thread.java:841)
E/dalvikvm(18292): VM aborting
A/libc(18292): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1), thread 18308 (Thread-55890)
I/DEBUG(17442): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG(17442): Build fingerprint: 'samsung/jfltexx/jflte:4.3/JSS15J/I9505XXUEMK9:user/release-keys'
I/DEBUG(17442): Revision: '11'
I/DEBUG(17442): pid: 18292, tid: 18308, name: Thread-55890  >>> com.example.datafeed <<<
I/DEBUG(17442): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadd00d
I/DEBUG(17442):     r0 00000000  r1 00000000  r2 00000000  r3 40b76e50
I/DEBUG(17442):     r4 deadd00d  r5 0000020c  r6 752342dc  r7 752342e3
I/DEBUG(17442):     r8 75336b38  r9 75225fb8  sl 75221638  fp 75336b4c
I/DEBUG(17442):     ip 47844001  sp 753368b8  lr 00000001  pc 40afd970  cpsr 60000030
01-17 10:57:55.342: I/DEBUG(17442):     d0  0000000000000000  d1  0000000000000000
01-17 10:57:55.342: I/DEBUG(17442):     d2  0000000000000000  d3  0000000000000000
01-17 10:57:55.342: I/DEBUG(17442):     d4  0010010200000010  d5  000000010000009c
01-17 10:57:55.342: I/DEBUG(17442):     d6  ffffffffffffffff  d7  3f8000003f800000
01-17 10:57:55.342: I/DEBUG(17442):     d8  0000000000000000  d9  0000000000000000
01-17 10:57:55.342: I/DEBUG(17442):     d10 0000000000000000  d11 0000000000000000
01-17 10:57:55.342: I/DEBUG(17442):     d12 0000000000000000  d13 0000000000000000
01-17 10:57:55.342: I/DEBUG(17442):     d14 0000000000000000  d15 0000000000000000
01-17 10:57:55.342: I/DEBUG(17442):     d16 6e616c2e6176616a  d17 6461657268542e67
01-17 10:57:55.342: I/DEBUG(17442):     d18 002e006300650073  d19 00700069006c0063
01-17 10:57:55.342: I/DEBUG(17442):     d20 00720061006f0062  d21 00430049002e0064
01-17 10:57:55.342: I/DEBUG(17442):     d22 006200700069006c  d23 006400720061006f
01-17 10:57:55.342: I/DEBUG(17442):     d24 ff00550055005500  d25 ff00550055005500
01-17 10:57:55.342: I/DEBUG(17442):     d26 ff00550055005500  d27 ff00550055005500
01-17 10:57:55.342: I/DEBUG(17442):     d28 ff00550055005500  d29 ff00550055005500
01-17 10:57:55.342: I/DEBUG(17442):     d30 0000000d000d000d  d31 0000000d000d000d
01-17 10:57:55.352: I/DEBUG(17442):     scr 60000010
01-17 10:57:55.352: I/DEBUG(17442): backtrace:
01-17 10:57:55.352: I/DEBUG(17442):     #00  pc 00048970  /system/lib/libdvm.so (dvmAbort+67)
01-17 10:57:55.352: I/DEBUG(17442):     #01  pc 0004d41b  /system/lib/libdvm.so (dvmDecodeIndirectRef(Thread*, _jobject*)+146)
01-17 10:57:55.352: I/DEBUG(17442):     #02  pc 0004e141  /system/lib/libdvm.so
01-17 10:57:55.352: I/DEBUG(17442):     #03  pc 00000cf3  /data/app-lib/com.example.datafeed-1/libdatafeed.so (Java_com_example_datafeed_DataFeed_decode+194)
01-17 10:57:55.352: I/DEBUG(17442):     #04  pc 0002048c  /system/lib/libdvm.so (dvmPlatformInvoke+112)
01-17 10:57:55.352: I/DEBUG(17442):     #05  pc 00050ff3  /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+398)
01-17 10:57:55.352: I/DEBUG(17442):     #06  pc 00052ca9  /system/lib/libdvm.so (dvmResolveNativeMethod(unsigned int const*, JValue*, Method const*, Thread*)+256)
01-17 10:57:55.352: I/DEBUG(17442):     #07  pc 00029920  /system/lib/libdvm.so
01-17 10:57:55.352: I/DEBUG(17442):     #08  pc 0002e2ec  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)
01-17 10:57:55.352: I/DEBUG(17442):     #09  pc 00063179  /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+292)
01-17 10:57:55.352: I/DEBUG(17442):     #10  pc 000631a3  /system/lib/libdvm.so (dvmCallMethod(Thread*, Method const*, Object*, JValue*, ...)+20)
01-17 10:57:55.352: I/DEBUG(17442):     #11  pc 00057f03  /system/lib/libdvm.so
01-17 10:57:55.352: I/DEBUG(17442):     #12  pc 0000cc60  /system/lib/libc.so (__thread_entry+72)
01-17 10:57:55.352: I/DEBUG(17442):     #13  pc 0000cddc  /system/lib/libc.so (pthread_create+208)

I notice that the java method is only being called once, despite CallObjectMethod being called twice (it prints the returned output, despite not printing the debug method from the java code). Not sure how to solve this, do I have to reset the reference ever time? If anyone has any suggestions will be much appreciated.

Edit: Not sure if this will help, but I've added the java code.

public class DataFeed {
    static {
        System.loadLibrary("datafeed");
    }
    private BlockingQueue<Byte> inputQueue;
    public DataFeed () {
        inputQueue=new LinkedBlockingQueue<Byte>();
}
public native void decode();

public byte[] getBytes (int bytes)  {
    int curbyte = 0;
    byte[] retbytes = new byte[bytes];
    Log.d("FEED", "getting " + bytes + " bytes");
    while(curbyte < bytes) {
        try {
            retbytes[curbyte] = inputQueue.take();

        } catch (InterruptedException e) {
            e.printStackTrace();
            return null;
        }
        curbyte ++;
    }
    Log.d("FEED", "returning " + retbytes.length + " bytes  ");
    return retbytes;


    }

    public void playData(short[] outdata) {
        Log.d("OUTPUT", "recieved " + outdata.length + " data");
    }
}

Upvotes: 1

Views: 6660

Answers (1)

marcinj
marcinj

Reputation: 50016

When calling GetByteArrayElements you should release pointer with ReleaseByteArrayElements not DeleteLocalRef. ex:

int fLen = env->GetArrayLength(getbytes_ret);
jbyte *temp = (jbyte *)(*env)->GetByteArrayElements(env, getbytes_ret, NULL);

__android_log_print(ANDROID_LOG_ERROR, "Native", "Array Set"); 
memcpy(data, temp, fLen );
__android_log_print(ANDROID_LOG_ERROR, "Native", "Memory Copied");

(*env)->ReleaseByteArrayElements(env, getbytes_ret, temp, 0 );

Upvotes: 2

Related Questions