2012-04-25 120 views
0

我對JNI看起來並沒有太多運氣。我正在等待我買的一本書到達,但現在它是反覆試驗。使用java JNI GetFieldID和JNI一般

我正在使用JNI來實現一個Lua評估器。 evaluateatorNew()只創建一個新的Evaluator()對象,按照Java方面的描述創建一個新的CPtr()類對象,將我們的Evaluator()對象的指針賦給CPtr的'peer'成員,並返回新的CPtr jobject。

JNIEXPORT jobject JNICALL Java_com_starlon_libscriptable_UtilsEvaluator_evaluatorNew(
    JNIEnv *env, jclass clazz) 
{ 
    int foo = 1; 
    while(foo); 

    Evaluator *eval = new Evaluator(); 

    jobject obj; 
    jclass tempClass; 

    tempClass = env->FindClass("com/starlon/libscriptable/CPtr"); 

    obj = env->AllocObject(tempClass); 
    if (obj) 
    { 
     env->SetLongField(obj, env->GetFieldID(tempClass, "peer", "J"), (jlong)eval); 
    } 
    return obj; 
} 

這裏是Java類來容納我們的指針。這就是'env-> FindClass()'正在調用的內容。

public class CPtr 
{ 
    /* Pointer value of the real C pointer. Use long to be 64-bit safe. */ 
    private long peer; 

    protected long getPeer() 
    { 
     return peer; 
    } 

    /* No-args constructor. */ 
    CPtr() {} 

} 

有沒有堆棧跟蹤可以說,你可以看到下面。

(gdb) bt 
#0 0xafd15ca8 in __libc_android_abort() 
    from /home/scott/workspace/StarVisuals/StarVisuals/obj/local/armeabi-v7a/libc.so 
#1 0x00000008 in ??() 
Backtrace stopped: frame did not save the PC 

下面是GDB通過上面的JNI功能步進轉儲:

0x80805258 in Java_com_starlon_libscriptable_UtilsEvaluator_evaluatorNew (env=0xabd8, 
    clazz=0x40715698) at jni/libscriptable//evaluator.cpp:85 
85  while(foo); 
Current language: auto; currently c++ 
(gdb) set foo = 0 
(gdb) s 
[New Thread 11226] 
[Switching to Thread 11226] 
87  Evaluator *eval = new Evaluator(); 
(gdb) u 
92  tempClass = env->FindClass("com/starlon/libscriptable/CPtr"); 
(gdb) u 
94  obj = env->AllocObject(tempClass); 
(gdb) u 
95  if (obj) 
(gdb) s 
97   env->SetLongField(obj, env->GetFieldID(tempClass, "peer", "J"), (jlong)eval); 
(gdb) s 
_JNIEnv::GetFieldID (this=0xabd8, clazz=0x40715910, name=0x8080a134 "peer", sig=0x8080a13c "J") 
    at /opt/android-ndk-r7b/platforms/android-9/arch-arm/usr/include/jni.h:708 
708  { return functions->GetFieldID(this, clazz, name, sig); } 
(gdb) print functions 
$1 = (const JNINativeInterface *) 0xaca9dd68 
(gdb) print this 
$2 = (_JNIEnv * const) 0xabd8 
(gdb) print clazz 
$3 = (jclass) 0x40715910 
(gdb) print name 
$4 = 0x8080a134 "peer" 
(gdb) print sig 
$5 = 0x8080a13c "J" 
(gdb) print *functions 
$6 = {reserved0 = 0x0, reserved1 = 0x0, reserved2 = 0x0, reserved3 = 0x0, GetVersion = 0xaca43385, 
    DefineClass = 0xaca43355, FindClass = 0xaca4773d, FromReflectedMethod = 0xaca47719, 
    FromReflectedField = 0xaca476f5, ToReflectedMethod = 0xaca476b9, GetSuperclass = 0xaca44801, 
    IsAssignableFrom = 0xaca4450d, ToReflectedField = 0xaca4767d, Throw = 0xaca43331, 
    ThrowNew = 0xaca47655, ExceptionOccurred = 0xaca447b1, ExceptionDescribe = 0xaca4761d, 
    ExceptionClear = 0xaca43315, FatalError = 0xaca44d99, PushLocalFrame = 0xaca475c1, 
    PopLocalFrame = 0xaca47561, NewGlobalRef = 0xaca44ac1, DeleteGlobalRef = 0xaca4502d, 
---Type <return> to continue, or q <return> to quit---q 
SetByteFieldQuit 
(gdb) print functions->GetFieldID 
$7 = (jfieldID (*)(JNIEnv *, jclass, const char *, const char *)) 0xaca47435 
(gdb) s 

Program received signal SIGSEGV, Segmentation fault. 
0xaca4cd0c in ??() 
(gdb) bt 
#0 0xafd15ca8 in __libc_android_abort() 
    from /home/scott/workspace/StarVisuals/StarVisuals/obj/local/armeabi-v7a/libc.so 
#1 0x00000008 in ??() 
Backtrace stopped: frame did not save the PC 
(gdb) quit 

這裏的jni.h線708:

jfieldID GetFieldID(jclass clazz, const char* name, const char* sig) 
{ return functions->GetFieldID(this, clazz, name, sig); } // 708 

任何幫助嗎?請讓我知道是否需要澄清任何事情。

回答

1

AllocObject分配但不構建對象。我懷疑SetLongField可能會猛烈地拋出,如果你在一個未構造的對象上調用它,就像你在這裏做的那樣。改爲使用NewObject;您必須首先查詢無參數構造函數的methodid。

+0

那麼,事實證明,這個問題是在其他地方,由於我使用的Lua庫因拋棄錯誤的Lua代碼而拋出異常。看來,逐步通過這些JNIEnv *方法(GetFieldID)會導致虛擬機出現故障。無論如何,我從你那裏學到了一些東西,所以這裏是積極的。 :) – Scott 2012-04-25 03:24:47

3

你的代碼需要很多理所當然的。你需要檢查每個結果,我的意思是每個, JNI調用,通過尋找一個異常,並且如果你得到一個異常,則中止。你不能像這樣堆疊函數調用Lisp風格,並希望它們都返回可用的值。