12

ここから、絶対初心者向けの本のAndroidアプリと温度コンバーターアプリからHello Worldアプリケーションを作成しました 両方ともエミュレーターでは正常に動作していますが、Samsung Note 2で実行しようとすると、LogCatで次のエラーが発生します

02-08 07:22:18.665: E/dalvikvm(30944): JNI ERROR (app bug): accessed stale local reference 0xbc00021 (index 8 in a table of size 8)
02-08 07:22:18.665: E/dalvikvm(30944): VM aborting
02-08 07:22:18.665: A/libc(30944): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1), thread 30944 (oid.temperature)

どちらのアプリケーションもタイトル付きのショー レイアウトを開きますが、レイアウトに他のビューは表示しません

サンプルは正常に実行されます

デバイス: 注 2 サムスン-gt_n7100

IDE:Eclipse バージョン 3.8

OS: 64 ビット Windows 7

4

1 に答える 1

66

Android 4.0 ガベージ コレクターが変更されたため。ガベージ コレクション中にオブジェクトを移動するため、多くの問題が発生する可能性があります。

オブジェクトを指す静的変数があり、このオブジェクトが gc によって移動されると想像してください。Android は Java オブジェクトに直接ポインタを使用するため、これは静的変数がメモリ内のランダムなアドレスを指していることを意味し、オブジェクトによって占有されていないか、別の種類のオブジェクトによって占有されています。これにより、次にこの変数を使用するときに EXC_BAD_ACCESS を取得することがほぼ保証されます。

そのため、Android は JNI ERROR (アプリのバグ) エラーを表示して、デバッグ不能な EXC_BAD_ACCESS を取得できないようにします。このエラーを回避する方法は 2 つあります。

  1. マニフェストで targetSdkVersion をバージョン 11 以下に設定できます。これにより、JNI バグ互換モードが有効になり、問題が完全に防止されます。これが、古い例が機能している理由です。

  2. env->NewGlobalRef(ref) を呼び出して、Java オブジェクトを指す静的変数の使用を避けるか、ジョブジェクトの参照をグローバルにしてから保存することができます。
    おそらくここでの最大の例は、jclass オブジェクトを保持することです。通常、JNI_OnLoad 中に静的な jclass 変数を初期化します。これは、アプリケーションが実行されている限りクラス オブジェクトがメモリ内に残るためです。

このコードはクラッシュを引き起こします:

static jclass myClass;

JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM * vm, void * reserved) {  
    myClass = env->FindClass("com/example/company/MyClass");  
    return JNI_VERSION_1_6;  
}

このコードは正常に実行されますが、次のようになります。

static jclass myClass;

JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM * vm, void * reserved) {  
    jclass tmp = env->FindClass("com/example/company/MyClass");  
    myClass = (jclass)env->NewGlobalRef(tmp);
    return JNI_VERSION_1_6;  
}

その他の例については、Marek Sebera が提供するリンクを参照してください: http://android-developers.blogspot.cz/2011/11/jni-local-reference-changes-in-ics.html

于 2013-07-03T13:18:13.997 に答える