java - JNI 报告 Android 中 GetByteArrayElements 的间接引用无效

标签 java android c java-native-interface

我有一个问题。我正在调用一个测试函数,该函数从 Java 导入函数获取多个字节,然后将该数据作为一个短数组返回。目前我遇到一个问题,即程序因间接引用而崩溃。我的代码是这样的:

#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);

 }

当我运行这段代码时,我得到了这样的输出:

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)

我注意到 java 方法只被调用一次,尽管 CallObjectMethod 被调用了两次(它打印返回的输出,尽管没有从 java 代码打印调试方法)。不知道如何解决这个问题,我是否必须每次都重置引用?如果有人有任何建议,将不胜感激。

编辑:不确定这是否有帮助,但我已经添加了 java 代码。

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

最佳答案

调用 GetByteArrayElements 时,您应该使用 ReleaseByteArrayElements 而不是 DeleteLocalRef 释放指针。例如:

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

关于java - JNI 报告 Android 中 GetByteArrayElements 的间接引用无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21184526/

相关文章:

java - Java 中如何杀死一个线程?

android - 如何确定Android中的语音信箱电话号码

android - firebase 项目中的应用程序实例是什么?它是独特用户的应用程序还是应用程序?

c - fread() 在 C 中的返回值

c - 删除 char 数组的字符

java - Twitter4j 用户 protected 数据的问题

java - 当我将文件从 servlet 发送到浏览器时,输出流会发生什么情况?

Android Studio 不删除我在 Adapter 中的项目?

在 C 中使用 sprintf 复制十六进制值

java - 在 Android 游戏逻辑中解锁关卡