2011-09-23 122 views
8

我試圖從Android應用程序中的本機C代碼調用java方法。這聽起來很簡單,但是在最終調用方法本身時,我的代碼總是崩潰。 這裏是我的代碼: 本機C代碼:當調用CallVoidMethod時JNI崩潰

JNIEXPORT void JNICALL 
Java_com_path_to_my_package_renderStuff(JNIEnv* env, jobject jobj){ 
//... 
jclass clazz = env->FindClass("com/path/to/the/class"); 
jmethodID showCar = env->GetMethodID(clazz,"showCar","()V"); 
env->CallVoidMethod(jobj,showCar); //If I comment this out, it won't crash 
//... 
} 

Java代碼:

public void showCar(){  
    doSomething() 
} 

DoSomething的()甚至沒有達到,我可以設置一個斷點,這將永遠不會被擊中。如上所述,只要我註釋掉CallVoidMethod調用,它就不會崩潰,但顯然不會調用showCar()。任何提示?

+0

你確定'FindClass'和'GetMethodID'實際上返回非空結果嗎? –

+0

是的,我們已經檢查了兩個結果,但似乎有二進制數據或其他東西。但它肯定不是空的。不幸的是,使用Android NDK和GDB調試本機代碼變得相當困難,因爲我們無法讓C Debugger工作。 – Lennart

回答

11

4的想法,爲您提供:

...

JCLASS clazz中= env-> FindClass後面( 「COM /路徑/到/的/類」);

您可以確認名稱不是「com/path/to/the/MyClass」,其中classname是大寫第1個字符,顯然名稱「class」是保留字。在您的示例中,在「com/path/to/the/class」上使用JNI C符號名稱「Java_com_path_to_my_package_renderStuff」和FindClass()查找之間存在細微差別。但由於你的stackoverflow不是一個關於UnsatisfiedLinkageError我只能猜測你提供的例子是不符合自己。

使用我的例子我期望JNI C符號名稱爲「Java_com_path_to_the_MyClass_renderStuff」,並在「com/path/to/the/MyClass」上查找FindClass()。對於連接目的,使用大寫的第一個字母的類和方法名的第一個小寫字母可能是重要的。

...

你確定了「jobj」傳遞是同類型的「COM /路徑/到/的/類」您正在尋找呢?也許在你的Java代碼中,你可以用你的本機包裝:

public void renderStuff() { 
    if((this instanceof com.path.to.the.MyClass) == false) 
     throw new RuntimeException("Unexpected class expected: com.path.to.the.MyClass"); 
    renderStuff_internal(); 
} 
private native void renderStuff_internal(); 

這將確保Java代碼中的事情不會導致JVM崩潰。您還需要調整你的C符號名稱追加了「_1internal」到年底制定「Java_com_path_to_the_MyClass_renderStuff_1internal」(額外的「1」字意)

...

也許嘗試帶和揹帶例外在你列出的每條語句之間進行檢查:

if(env->ExceptionCheck()) { 
    env->ExceptionDescribe(); 
    env->ExceptionClear(); 
} 

這會在不允許的情況下嘗試進行反射時發現安全違規事件。

...

jclass cls = env->GetObjectClass(jobj); // instead of FindClass 
jmethodID mid = env->GetMethodID(cls, "showCar", "()V"); 
if(!mid) return; // whoops method does not exist 
env->CallVoidMethod(jobj, mid); 

另一個想法去除的findClass()調用。這可以與GetMethodID的任何類一起工作,類似於dyhamic類型/後期綁定。

+0

使用GetObjectClass()而不是FindClass是我需要知道的。 – Alyoshak