2011-09-23 17 views
8

AndroidアプリケーションのネイティブCコードからjavaメソッドを呼び出そうとしています。これはJNIの使用法では非常に単純ですが、最終的にメソッド自体を呼び出すと、私のコードは常にクラッシュします。 ネイティブ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'が実際にnull以外の結果を返すようにしましたか? –

+0

はい、両方の結果を確認しましたが、バイナリデータなどがあるようです。しかし、それは間違いなくヌルではありません。残念なことに、Android NDKとGDBを使ってネイティブコードをデバッグすることは、Cデバッガをまったく動作させることができないため、非常に困難でした。 – Lennart

答えて

11

4アイデア:

...

JCLASS clazz = env-> FindClassが( "COM /パス/に/クラス/");

名前が大文字の第1文字である「com/path/to/the/MyClass」ではないことを確認できますか?明らかに「class」という名前が予約語です。あなたの例では、 "Java_com_path_to_my_package_renderStuff"と "com/path/to/the/class"のFindClass()ルックアップのJNI Cシンボル名の使用の間にわずかな違いがあります。しかし、あなたのstackoverflowはUnsatisfiedLinkageErrorに関するものではないので、私はあなたの例がそれ自身と一貫していないと推測できます。

私の例では、JNI Cのシンボル名は "Java_com_path_to_the_MyClass_renderStuff"、FindClass()は "com/path/to/the/MyClass"のルックアップになります。リンケージのためには、大文字の第1文字クラスとメソッド名の最初の文字を使用することが重要です。

...

あなたは「jobj」渡されているが、あなたは「COM /パス/に/クラス/」と同じタイプ見上げているされてよろしいですか?

JVMのクラッシュを引き起こすことなく、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コードであなたがあなたのネイティブをラップすることができます。また、多分ベルトを試してみて、例外をブレース

...

(余分な「1」の文字が意図している)「Java_com_path_to_the_MyClass_renderStuff_1internal」作り最後に「_1internal」を追加し、あなたのCのシンボル名を調整する必要がありますあなたはリストそれぞれの文の間にチェックイン:

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 typing/late-bindingのようなもので動作します。

+0

FindClassの代わりにGetObjectClass()を使用することは、私が知る必要があるものでした。 – Alyoshak

関連する問題