web-dev-qa-db-ja.com

Android ICS:JNIエラーが古いローカル参照0x1を使用しようとしました

私の電話をAndroid 4.03 icsにアップグレードした後、私のゲームはもう開かれていません、それはデバイスでエラーメッセージなしで、そしてこれでEclipseで閉じます

04-02 16:55:27.672: E/dalvikvm(26884): JNI ERROR (app bug): attempt to use stale local reference 0x1
04-02 16:55:27.672: E/dalvikvm(26884): VM aborting

私のゲームは主にJavaで書かれていますが、いくつかの部分はcであり、それが問題だと思います(JNIエラーと言っているので理解するのはそれほど難しいことではありません:))

もちろん、私は問題がどこにあるのかわからないので、コードを与えません

Android 2.3ではこの問題は発生しませんでした

それが役立つかどうかはわかりませんが、このエラーが発生することもあります

04-02 16:55:26.061: E/Adreno200-ES11(26884): <qglDrvAPI_glTexImage2D:1913>: GL_STACK_UNDERFLOW
20
SteveL

アーネストの answer は技術的には正しいですが、0x1のような古いローカル参照は、Java VMがしようとしていることを示唆しているはずです。 JavaオブジェクトではないものをJavaオブジェクトとして使用します。

たとえば、JNI関数が次のようになっていると仮定します。

JNI_EXPORT jboolean foobar(JNIEnv *env, jobject self) {
  ...
  return JNI_TRUE;
}

しかし、誤ってJava対応物をpublic native Boolean foobar()ではなくpublic native boolean foobar()として宣言しました。

booleanBooleanの唯一の違いは大文字であるため、これは簡単な間違いです。

  • プリミティブ型であるbooleanは、JNIではbooleanとして表されます。
  • Java.lang.Booleanは、Booleanとも呼ばれ、JNIではjobjectとして表されるクラスタイプです。

foobarから戻ると、Java VMはJNI_TRUE値(0x1)をJava.lang.Booleanオブジェクトを参照しているかのように扱います。この致命的なエラーが発生します。

21
Ilya

「古いローカル参照」エラーは、JNI呼び出しの間にいくつかのJavaオブジェクトへのローカル参照を保存していることを意味します。何かを行う前に、NewGlobalRefメソッドを使用してその参照をグローバル参照に変換する必要がありますこれにより、参照が1つのJNI呼び出しの範囲外で存続します。

厳密にはこれは常に必要でしたが-JNI仕様に含まれています-これが実際にAndroidプラットフォームで問題を引き起こすのは、アイスクリームサンドイッチ以来です。

29

@Ernestと@Ilyaは正しいです。この問題は、署名の不一致だけでなく、他の方法でも現れることに注意してください。私が遭遇した別の非常に特殊なケースがあります。これは、Androidのチームのブログのセクションで説明されています ここ

バグ:FindClass()がグローバル参照を返すと誤って想定している

FindClass()はローカル参照を返します。多くの人はそうではないと思います。クラスのアンロードがないシステム(Androidなど)では、jfieldIDとjmethodIDをグローバルであるかのように扱うことができます。 (これらは実際には参照ではありませんが、クラスのアンロードがあるシステムでは、同様の有効期間の問題があります。)ただし、jclassは参照であり、FindClass()はローカル参照を返します。一般的なバグパターンは「静的jclass」です。ローカル参照をグローバル参照に手動で変換しない限り、コードは壊れています。

基本的に、jclassによって返されたFindClassをグローバル変数にそのままキャッシュしていましたが、この値(Android 4?)の時点で)は現在localref。その結果、次のようにglobalrefに変換する必要がありました。

jclass jc = env->FindClass(callbacks.name);
// Since Android ICS, class references are not global so we need to peg a
// global reference to the jclass returned by FindClass(), otherwise we get
// following error in the log:
// "JNI ERROR (app bug): attempt to use stale local reference 0xHHHHHHHH".
callbacks._class = static_cast<jclass>(env->NewGlobalRef(jc));

多くの頭を悩ませた後、これは私にとって問題を修正しました。

13
scorpiodawg

これはアーネストの答えのバリエーションであり、呼び出しメソッドの引数としてブール値またはブール値を渡す代わりに、もちろん値が0x1のリテラルtrueを渡しました(はい、それを見つけたときに繰り返しキックしました)。 。

1
user330844

他の答えの妥当性に異議を唱えることはしませんでしたが、私はこれらのエラーを追いかける時間を失いました。私の場合、彼らは本当に謎めいたものでしたが、私だけが責任を負っています。

10-16 12:24:18.722:E/dalvikvm(1204):JNIエラー(アプリのバグ):古いグローバル参照0x26を使用しようとしました
10-16 12:24:18.722:E/dalvikvm(1204):VM中止

私にとって、これはマニフェストで正しい許可を要求していなかったことを意味しました。

0
John

私の場合、NewObjectを呼び出すときに、コンストラクターに必要ないくつかの引数(メソッドの呼び出しにも適用される可能性があります)を渡すことができませんでした。

0
KYHSGeekCode