2011-09-12 29 views
5

Tôi gặp sự cố JNI mà tôi hy vọng ai đó có thể giúp tôi.
Tôi đang cố gắng gọi một hàm tạo của một lớp Java có tên là LUSOutputJNI từ một chuỗi gốc.
Nó không làm hỏng trên FindClass (...) của lớp học cụ thể này.Sự cố khi gọi phương thức Java từ chủ đề gốc bằng JNI (C++)

Đây là mã:

LOGE("1"); 
    JNIEnv *env = NULL; 

    LOGE("2"); 
    int res = -1; 
    res = g_vm->AttachCurrentThread(&env, NULL); 

    if(env == NULL) 
    { 
     LOGE("env is NULL, AttachCurrentThread failed");; 
    } 


    if(res >= 0) 
     LOGE("AttachCurrentThread was successful"); 
    jclass clazz = NULL; 
    jmethodID cid; 

    jclass clazzESEngine; 
    jmethodID callbackid; 

    jobject jCoreOut; 
    static jfieldID fid_ActionState = NULL; 
    static jfieldID fid_nSpeed = NULL; 
    static jfieldID fid_nType = NULL; 
    static jfieldID fid_nInProcess = NULL; 
    static jfieldID fid_nX = NULL; 
    static jfieldID fid_nY = NULL; 
    LOGE("3"); 

    static const char* const ECOClassName = "lus/android/sdk/LUSOutputJNI"; 
    //static const char* const ECOClassName = "android/widget/TextView"; 
    clazz = env->FindClass(ECOClassName); 
    if (clazz == NULL) { 
     LOGE("Can't find class LUSOutputJNI"); 

    } 
    else 
     LOGE("lus/android/sdk/LUSOutputJNI was found, YEY!!"); 

    LOGE("4"); 
    cid = env->GetMethodID(clazz,"<init>", "()V"); 
    LOGE("5"); 
    jCoreOut = env->NewObject(clazz, cid); 

    LOGE("6");  

Đây là kết quả logcat từ khi nó không thành công:

E/lusCore_JNI(3040): 1 
E/lusCore_JNI(3040): 2 
E/lusCore_JNI(3040): AttachCurrentThread was successful 
E/lusCore_JNI(3040): 3 
E/lusCore_JNI(3040): Can't find class LUSOutputJNI 
E/lusCore_JNI(3040): 4 
W/dalvikvm(3040): JNI WARNING: JNI method called with exception raised 

Quan sát:

  • tôi nhận được một kết quả từ AttachCurrentThread là 0, whic h có nghĩa là tập tin đính kèm này đã thành công + con trỏ env không còn là NULL.
  • Tôi chắc chắn về việc khai báo tên gói của LUSOutputJNI (gấp ba lần kiểm tra ...)
  • Khi tôi cố gắng chạy FindClass (..) với tên lớp phổ biến hơn như android/widget/TextView, I có được một trận đấu tích cực. Nó ở đó. Có nghĩa là các tập tin đính kèm thread và các biến env là ok. (Tôi có thể giả định điều đó không?)
  • Khi tôi cố gắng chạy đoạn mã sau từ một phương pháp JNI có chuỗi JNI chạy nó, nó tìm thấy lớp LUSOutputJNI mà không có vấn đề gì.

Tôi đang làm gì sai?

Trợ giúp sẽ được nhiều đánh giá cao :)

Cảm ơn thời gian của bạn,

Ita

+0

Bất kỳ tham chiếu nào đến lớp 'LUSOutputJNI' này? –

+0

@ K-ballo: Đây có thể là một lớp học trong nhà. –

+0

@Ita: Trình khởi tạo tĩnh LUSOutputJNI của bạn có ném ngoại lệ không? Bạn nên in ngoại lệ được nêu ra. –

Trả lời

6

Tìm câu trả lời \ làm việc ở đây. (Tìm Câu hỏi thường gặp: "FindClass không tìm thấy lớp của tôi" trong JNI tips)

Tôi cơ bản đã lưu ref toàn cầu cho các đối tượng jclass cần thiết.
Tuy nhiên, đã phải vượt qua một số thay đổi JNI ác giữa C/JNI và C++/JNI để mã biên dịch.
Đây là cách tôi nhận NewGlobalRef để biên dịch và hoạt động.

jclass localRefCls = env->FindClass(strLUSClassName); 
if (localRefCls == NULL) { 
    LOGE("Can't find class %s",strLUSCoreClassName); 
    return result; 
} 

//cache the EyeSightCore ref as global 
/* Create a global reference */ 
clazzLUSCore = (_jclass*)env->NewGlobalRef(localRefCls); 

/* The local reference is no longer useful */ 
env->DeleteLocalRef(localRefCls); 

/* Is the global reference created successfully? */ 
if (clazzLUSCore == NULL) { 
    LOGE("Error - clazzLUSCore is still null when it is suppose to be global"); 
    return result; /* out of memory exception thrown */ 
} 

Tôi hy vọng điều này sẽ giúp mọi người.

+0

Cảm ơn, điều này đã giúp. Là nó thực sự cần thiết để xóa ref địa phương ở đây? Tôi tin rằng chúng sẽ tự động bị xóa khi hàm trả về: http://android-developers.blogspot.co.il/2011/11/jni-local-reference-changes-in-ics.html – snowdragon

2

Để biết thêm một chút thông tin về những gì đang diễn sai (nó sẽ đăng nhập vào thiết bị lỗi chuẩn, không Loge, và tôi không chắc chắn làm thế nào để thay đổi điều đó), bạn có thể thêm một số ngoại lệ in ấn - bạn có thể thay đổi điều này:

//static const char* const ECOClassName = "android/widget/TextView"; 
clazz = env->FindClass(ECOClassName); 
if (clazz == NULL) { 
    LOGE("Can't find class LUSOutputJNI"); 

} 
else 
    LOGE("lus/android/sdk/LUSOutputJNI was found, YEY!!"); 

để này:

//static const char* const ECOClassName = "android/widget/TextView"; 
    clazz = env->FindClass(ECOClassName); 
    if (clazz == NULL) { 
     LOGE("Can't find class LUSOutputJNI"); 
     jthrowable exc = env->ExceptionOccurred(); 
     if(exc) 
     { 
      env->ExceptionDescribe(); 
      env->ExceptionClear(); 
     }  
    } 
    else 
     LOGE("lus/android/sdk/LUSOutputJNI was found, YEY!!"); 
+1

Có vẻ như bạn có thể lấy thông tin lỗi bằng cách sử dụng hàm toString bên trong jthrowable, sau đó chuyển đổi thành chuỗi C và đặt nó vào hàm 'LOGE' của bạn, nhưng có thể quá mức cần thiết để gỡ lỗi này. –

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