2015-04-26 13 views
12


Tôi đang viết một ứng dụng Android xử lý ảnh từ nguồn gốc C (NDK r10d). Mã này hoạt động tốt cho đến khi giới thiệu ART gần đây nghiêm ngặt hơn với JNI. Vì vậy, mã hoạt động tốt với Dalvik (ví dụ: trên các thiết bị trước Lolipop) nhưng ii tạo một SIGENV trên các điện thoại mới nhất.
bây giờ tôi nhận được lỗi:Lỗi Android (ART) với lỗi JNI DETECTED ERROR IN APPLICATION: jarray là bảng tham chiếu gián tiếp gián tiếp hoặc tham chiếu không hợp lệ

04-26 16:18:34.169: E/art(21443): 0xb4a2dd00 SpaceTypeMallocSpace begin=0x12c00000,end=0x12e01000,limit=0x32c00000,size=2MB,capacity=192MB,non_growth_limit_capacity=512MB,name="main rosalloc space"] 
04-26 16:18:34.170: E/art(21443): 0xb4ae5640 allocspace main rosalloc space live-bitmap 3[begin=0x12c00000,end=0x32c00000] 
04-26 16:18:34.170: E/art(21443): 0xb4ae5660 allocspace main rosalloc space mark-bitmap 3[begin=0x12c00000,end=0x32c00000] 
04-26 16:18:34.170: E/art(21443): 0xb4874120 SpaceTypeImageSpace begin=0x6f5ab000,end=0x6ff21e58,size=9MB,name="/data/dalvik-cache/arm/[email protected]@boot.art"] 
04-26 16:18:34.170: E/art(21443): 0xb4875220 imagespace /data/dalvik-cache/arm/[email protected]@boot.art live-bitmap 0[begin=0x6f5ab000,end=0x6ff21f00] 
04-26 16:18:34.170: E/art(21443): 0xb4875220 imagespace /data/dalvik-cache/arm/[email protected]@boot.art live-bitmap 0[begin=0x6f5ab000,end=0x6ff21f00] 
04-26 16:18:34.170: E/art(21443): 0xb49d9dd0 SpaceTypeZygoteSpace begin=0x72f09000,end=0x740c7000,size=17MB,name="Zygote space"] 
04-26 16:18:34.170: E/art(21443): 0xb4875440 allocspace zygote/non moving space live-bitmap 0[begin=0x72f09000,end=0x740c7000] 
04-26 16:18:34.170: E/art(21443): 0xb4875460 allocspace zygote/non moving space mark-bitmap 0[begin=0x72f09000,end=0x740c7000] 
04-26 16:18:34.170: E/art(21443): 0xb4a2dc80 SpaceTypeMallocSpace begin=0x740c7000,end=0x740d6000,limit=0x76f09000,size=60KB,capacity=46MB,non_growth_limit_capacity=46MB,name="non moving space"] 
04-26 16:18:34.170: E/art(21443): 0xb4ae5460 allocspace non moving space live-bitmap 4[begin=0x740c7000,end=0x76f09000] 
04-26 16:18:34.170: E/art(21443): 0xb4ae53c0 allocspace non moving space mark-bitmap 4[begin=0x740c7000,end=0x76f09000] 
04-26 16:18:34.170: E/art(21443): 0xb486d340 large object space:GcRetentionPolicyAlwaysCollect 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: jarray is an invalid stack indirect reference table or invalid reference: 0x740c9268 (0xdead4321) 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65]  in call to GetByteArrayElements 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65]  from boolean com.googlecode.leptonica.android.Pix.nativeGetData(int, byte[]) 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] "main" prio=5 tid=1 Runnable 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] | group="main" sCount=0 dsCount=0 obj=0x72f09000 self=0xb4827800 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] | sysTid=21443 nice=0 cgrp=default sched=0/0 handle=0xb6f6abec 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] | state=R schedstat=(427402282 63106827 397) utm=28 stm=14 core=3 HZ=100 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] | stack=0xbe5e3000-0xbe5e5000 stackSize=8MB 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] | held mutexes= "mutator lock"(shared held) 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #00 pc 00004e64 /system/lib/libbacktrace_libc++.so (UnwindCurrent::Unwind(unsigned int, ucontext*)+23) 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #01 pc 00003665 /system/lib/libbacktrace_libc++.so (Backtrace::Unwind(unsigned int, ucontext*)+8) 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #02 pc 00256429 /system/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, int, char const*, art::mirror::ArtMethod*)+84) 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #03 pc 00238fe7 /system/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const+158) 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #04 pc 000b191b /system/lib/libart.so (art::JniAbort(char const*, char const*)+610) 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #05 pc 000b2055 /system/lib/libart.so (art::JniAbortF(char const*, char const*, ...)+68) 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #06 pc 000b4455 /system/lib/libart.so (art::ScopedCheck::Check(bool, char const*, ...) (.constprop.129)+480) 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #07 pc 000bee03 /system/lib/libart.so (art::CheckJNI::GetByteArrayElements(_JNIEnv*, _jbyteArray*, unsigned char*)+62) 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #08 pc 00239478 /data/app/com.bill2bin.core.lib.demo-1/lib/arm/liblept.so (_JNIEnv::GetByteArrayElements(_jbyteArray*, unsigned char*)+48) 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #09 pc 0023992c /data/app/com.bill2bin.core.lib.demo-1/lib/arm/liblept.so (Java_com_googlecode_leptonica_android_Pix_nativeGetData+540) 
04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #10 pc 0008d3b5 /data/dalvik-cache/arm/[email protected]@[email protected]@classes.dex (Java_com_googlecode_leptonica_android_Pix_nativeGetData__I_3B+104) 
04-26 16:18:34.264: A/art(21443): art/runtime/check_jni.cc:65] at com.googlecode.leptonica.android.Pix.nativeGetData(Native method) 
04-26 16:18:34.264: A/art(21443): art/runtime/check_jni.cc:65] at com.googlecode.leptonica.android.Pix.getData(Pix.java:94) 
04-26 16:18:34.264: A/art(21443): art/runtime/check_jni.cc:65] at com.bill2bin.core.lib.demo.VideoPipeDebug.testDoJNIDebug(VideoPipeDebug.java:449) 
04-26 16:18:34.264: A/art(21443): art/runtime/check_jni.cc:65] at com.bill2bin.core.lib.demo.CameraActivity.runTest1(CameraActivity.java:133) 

Mã tôi chạy trong Java là:

/** 
    * Return the raw bytes of the native PIX object. You can reconstruct the 
    * Pix from this data using createFromPix(). 
    * 
    * @return a copy of this PIX object's raw data 
    */ 
    public byte[] getData() { 
     int size = nativeGetDataSize(mNativePix); 
     // Size is usually quite big since I work on pictures (1Mo-300Ko) 
     byte[] buffer = new byte[size]; 

     if (!nativeGetData(mNativePix, buffer)) { 
      throw new RuntimeException("native getData failed"); 
     } 

     return buffer; 
    } 

    private static native boolean nativeGetData(long nativePix, byte[] data); 

Các mã nguồn gốc tương ứng là:

jboolean Java_com_googlecode_leptonica_android_Pix_nativeGetData(JNIEnv *env, 
     jclass clazz, jlong nativePix, jbyteArray data) { 
    PIX *pix = (PIX *) nativePix; 

    jbyte *data_buffer = env->GetByteArrayElements(data, NULL); 

    l_uint8 *byte_buffer = (l_uint8 *) data_buffer; 

    size_t size = 4 * pixGetWpl(pix) * pixGetHeight(pix); 
    memcpy(byte_buffer, pixGetData(pix), size); 

    env->ReleaseByteArrayElements(data, data_buffer, 0); 

    return JNI_TRUE; 
} 

Dường như GetByteArrayElements là nguồn gốc của lỗi, nhưng tham chiếu JNIEnv và jbyteArray được cung cấp bởi Android và tôi không lưu trữ hoặc sửa đổi chúng. Kể từ khi mảng đệm luôn được phân bổ trong cùng một chuỗi Java, tôi không thấy nó có thể bị hỏng ... Tôi khá bối rối :)
Điều gì có thể là nguồn gốc của vấn đề này?
Heap có quá nhỏ không? Hay nó là một vấn đề ART (tôi thực sự nghi ngờ nó mặc dù ...)?
Cảm ơn sự giúp đỡ của bạn!

+2

Vui lòng kiểm tra kích thước được trả về bởi 'nativeGetDataSize()' và 'env-> GetArrayLength()' thực sự trả về giống nhau. Không yêu cầu giải quyết vấn đề này, tôi vẫn sẽ đề xuất phân bổ mảng trong mã gốc, loại bỏ một nửa số cuộc gọi JNI với tất cả các phí liên quan. –

+1

Thật không may, điều này xác nhận rằng tham chiếu của jbyteArray bị hỏng: cuộc gọi đến 'env-> GetArrayLength()' hiện đang trigerring cùng một lỗi. Tôi sẽ thử ngày mai phân bổ từ bên trong mã gốc. Cảm ơn! – Stef

+1

Hoạt động như một sự quyến rũ! cảm ơn! – Stef

Trả lời

4

Sau lời khuyên Alex Cohn của tôi đã thực hiện công việc mã sau:
JAVA

public byte[] getData() { 
     byte[] buffer = nativeGetData(mNativePix); 

     if (buffer == null) { 
      throw new RuntimeException("native getData failed"); 
     } 
     return buffer; 
    } 
    private static native byte[] nativeGetData(long nativePix); 


Native

jbyteArray Java_com_googlecode_leptonica_android_Pix_nativeGetData(
     JNIEnv *env, jclass clazz, jlong nativePix) { 
    PIX *pix = (PIX *) nativePix; 
    // Get the size 
    size_t size = 4 * pixGetWpl(pix) * pixGetHeight(pix); 

    jbyteArray result = env->NewByteArray(size); 
    if (result == NULL) { 
     LOGE("Cannot allocate JNI Byte Array"); 

     return NULL; /* out of memory error thrown */ 
    } 
    // move from the Pix to the java structure 
    env->SetByteArrayRegion(result, 0, size,(jbyte*)pixGetData(pix)); 
    return result; 
} 


Cảm ơn!

1

Điều này có nghĩa là nó hợp lệ trong thời gian của phương pháp gốc hiện tại trong chuỗi hiện tại. Ngay cả khi chính đối tượng tiếp tục tồn tại sau khi phương thức gốc trả về, tham chiếu không hợp lệ.

Hãy thử thay thế điều này trong lớp jclass/jarray của bạn.

jclass localClass = env->FindClass("MyClass"); 
jclass globalClass = reinterpret_cast<jclass>(env->NewGlobalRef(localClass)); 

Tham khảo JNI Tips

+0

Xin lỗi, tôi không chắc chắn để hiểu. Các jarray được phân bổ trong phần java, trong một chủ đề, sau đó được trao cho JNI. Tôi quên đề cập đến rằng người gọi của hàm java tôi trích dẫn được đồng bộ. Sau đó, jarray chỉ được sử dụng trong quá trình thực hiện hàm JNI, do đó, tham chiếu cục bộ phải được sử dụng tốt ở đây, phải không? Tuy nhiên, tôi cũng đã cố gắng để tạo ra một tham chiếu toàn cầu từ jarray nhưng điều này không thay đổi tình hình. – Stef

Các vấn đề liên quan