20

After upgrading my phone to android 4.03 ics my game dosent open anymore ,it just closes without any error messege on deviCe and with this on 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

My game is mainly writen in java but some parts are in c and thats were i think the problem is (not very hard to figure out since its saying JNI ERROR :) )

Of course i dont know where the problem is so i dont give any code

I didnt had this problem on android 2.3

I dont know if it helps but i get this error too sometimes

04-02 16:55:26.061: E/Adreno200-ES11(26884): <qglDrvAPI_glTexImage2D:1913>: GL_STACK_UNDERFLOW
SteveL
  • 3,331
  • 4
  • 32
  • 57

6 Answers6

30

The "stale local reference" error means that you're saving a local reference to some Java object between JNI calls; you need to convert that reference to a global reference using the NewGlobalRef method before doing anything that would cause the reference to persist outside the scope of the one JNI call.

Although strictly this was always necessary -- it's in the JNI spec -- it's only since Ice Cream Sandwich that this actually causes problems on the Android platform.

Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186
  • 7
    Finally! . The reference's didnt seem to be the problem , actually the real problem was quite silly .In my c code a had a void function but in java i was declaring it as native float[]... Thank you for you help – SteveL Apr 02 '12 at 15:33
  • 1
    @SteveL Thank you! I did the exact same thing (an early version of my native code returned a long, but I changed it to void in .c file and forgot to update in the .java. – Matt Apr 11 '12 at 13:54
  • If any of you have a chance to help me out i'm completely lost...http://stackoverflow.com/questions/14984132/jni-local-reference-changes-in-ics – JuiCe Feb 20 '13 at 16:24
  • @Ernest mate i m new to android and facing the same problem http://stackoverflow.com/questions/21423036/sqlite3-exception-database-disk-image-is-malformed pls tell how can i implement your code.. i m rectifying it from last 3 weeks :( – Maveňツ Jan 31 '14 at 12:35
23

While Ernest's answer is technically correct, a stale local reference to something like 0x1 should hint you that the Java VM is trying to use something that's not a Java object as a Java object.

For example, let's assume your JNI function is:

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

but you erroneously declare the Java counterpart as public native Boolean foobar() instead of public native boolean foobar().

It's an easy mistake to make, since the only difference between boolean and Boolean is capitalization.

  • boolean, a primitive type, is represented in JNI as boolean
  • java.lang.Boolean, known also as Boolean, is a class type that is represented in JNI as jobject

Upon return from foobar, the Java VM will treat the JNI_TRUE value (0x1) as if it referred to a java.lang.Boolean object, which will result in this fatal error.

Community
  • 1
  • 1
Ilya
  • 5,533
  • 2
  • 29
  • 57
13

@Ernest and @Ilya are correct. Note that the problem manifests itself in other ways too, not just signature mismatches. There is another very specific case that I ran into, which was explained here in the Android' team's blog under the section:

Bug: Mistakenly assuming FindClass() returns global references

FindClass() returns local references. Many people assume otherwise. In a system without class unloading (like Android), you can treat jfieldID and jmethodID as if they were global. (They’re not actually references, but in a system with class unloading there are similar lifetime issues.) But jclass is a reference, and FindClass() returns local references. A common bug pattern is “static jclass”. Unless you’re manually turning your local references into global references, your code is broken.

Basically I was caching the jclass returned by FindClass in a global variable as is, but it turns out this value (as of Android 4?) is now a localref. As a result, I had to convert it into a globalref like so:

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));

After a lot of head-scratching, this fixed the issue for me.

scorpiodawg
  • 5,612
  • 3
  • 42
  • 62
  • 1
    I've been through the same thing this week. I followed your solution and my crash was gone. On a side note: my test device (Asus Zenfone 2, running Android KitKat) did NOT present the issue, so I only saw the crash after the game went to Google Play and some friends installed it on Motorolas and Samsungs. – B.R.W. Jun 09 '16 at 16:49
1

This is a variation on Ernest's answer, instead of passing a Boolean or even a boolean as an argument to the call method, I passed the literal true ( yes I did kick myself repeatedly when I found that) which of course has the value of 0x1.

user330844
  • 872
  • 1
  • 12
  • 12
0

While not challenging the validity of the other answers, I lost hours chasing these errors. In my case they were truly cryptic but I've only myself to blame:

10-16 12:24:18.722: E/dalvikvm(1204): JNI ERROR (app bug): attempt to use stale global reference 0x26
10-16 12:24:18.722: E/dalvikvm(1204): VM aborting

For me, this meant I hadn't requested the correct permission in the manifest.

John
  • 6,433
  • 7
  • 47
  • 82
0

In my case I missed passing some arguments required for the constructor(also may apply to calling methods) when calling NewObject.

KYHSGeekCode
  • 1,068
  • 2
  • 12
  • 30