Reputation: 31
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
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