Bug 6696 - JNI Error (app bug) While running the app in Android device[ICS]
Summary: JNI Error (app bug) While running the app in Android device[ICS]
Status: RESOLVED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: Mono runtime / AOT Compiler ()
Version: 4.2.x
Hardware: Other Other
: --- normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2012-08-26 23:48 UTC by Surya Prakash
Modified: 2012-10-13 00:41 UTC (History)
3 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
example case that I couldn't reproduce with. (3.39 KB, text/plain)
2012-09-24 03:15 UTC, Atsushi Eno
Details
Error Raised during the Freeze and crash of the application (13.31 KB, text/plain)
2012-10-09 00:58 UTC, Surya Prakash
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Surya Prakash 2012-08-26 23:48:12 UTC
Hi,

I get this error, while I try to run the application,

Also, this error appears to be random and it always occur in ine particular module where I am needed to get a byte[] from network stream.

E/dalvikvm( 4797): JNI ERROR (app bug): accessed stale global reference 0x1d400716 (index 453 in a table of size 453)
E/dalvikvm( 4797): VM aborting
I/mono    ( 4797): Stacktrace:
I/mono    ( 4797): 
I/mono    ( 4797):   at Android.Runtime.JNIEnv.NewGlobalRef (intptr) <0x00043>
I/mono    ( 4797):   at Java.Lang.Object.RegisterInstance (Android.Runtime.IJavaObject,intptr,Android.Runtime.JniHandleOwnership) <0x0009b>
I/mono    ( 4797):   at Java.Lang.Object.SetHandle (intptr,Android.Runtime.JniHandleOwnership) <0x00023>
I/mono    ( 4797):   at Java.Lang.Object..ctor (intptr,Android.Runtime.JniHandleOwnership) <0x0003f>
I/mono    ( 4797):   at Java.Lang.String..ctor (intptr,Android.Runtime.JniHandleOwnership) <0x00023>
I/mono    ( 4797):   at Java.Interop.JavaConvert.<JniHandleConverters>m__55 (intptr,Android.Runtime.JniHandleOwnership) <0x00037>
I/mono    ( 4797):   at Java.Interop.JavaConvert.FromJavaObject<T> (Android.Runtime.IJavaObject) <0x0018f>
I/mono    ( 4797):   at Java.Interop.JavaConvert.FromJniHandle<T> (intptr,Android.Runtime.JniHandleOwnership) <0x0006b>
I/mono    ( 4797):   at Android.Runtime.JNIEnv.CopyObjectArray<T> (intptr,T[]) <0x00073>
I/mono    ( 4797):   at Android.OS.AsyncTask`3.Execute (TParams[]) <0x001a3>
I/mono    ( 4797):   at Dashmate.PickupDeliveryActivity/<>c__DisplayClass9/<>c__DisplayClassc.<OnCreate>b__6 (object,Android.Content.DialogClickEventArgs) <0x002af>
I/mono    ( 4797):   at Android.Content.IDialogInterfaceOnClickListenerImplementor.OnClick (Android.Content.IDialogInterface,int) <0x0005f>
I/mono    ( 4797):   at Android.Content.IDialogInterfaceOnClickListenerInvoker.n_OnClick_Landroid_content_DialogInterface_I (intptr,intptr,intptr,int) <0x00063>
I/mono    ( 4797):   at (wrapper dynamic-method) object.a450890f-a208-4fc0-902a-3d9b8580d115 (intptr,intptr,intptr,int) <0x0003b>
I/mono    ( 4797):   at (wrapper native-to-managed) object.a450890f-a208-4fc0-902a-3d9b8580d115 (intptr,intptr,intptr,int) <0xffffffff>
Comment 1 Jonathan Pryor 2012-08-29 11:56:07 UTC
Which Mono for Android version?

What type parameters are you using with your Android.OS.AsyncTask<,,> subclass?
Comment 2 Surya Prakash 2012-08-29 23:13:57 UTC
I am using string Parameters (AsyncTask<string,string,string>

And Within That class, I am using a web-service to download a stream of bytes(byte[]).
Comment 3 Atsushi Eno 2012-09-20 23:46:50 UTC
Could you provide pieces of code from your project that does the problematic work so that we can actually try? I guess there may be some problematic code inside the body of Execute() method.
Comment 4 Surya Prakash 2012-09-21 00:07:20 UTC
class DownloadHelper : AsyncTask<string,string,string>
	{
		const string TAG = "DownloadHelper";
		Context m_ctx;


		public DownloadHelper (Context context)
		{
			m_ctx = context;
			Log.Info (TAG, "Initialized Download Helper");
		}

		protected override string RunInBackground (string[] param)
		{
			Log.Info (TAG, "Entered Download Helper");
string fileName= param[0];
			try {
//Using a Local WebService
				Remote.Service.WebService service = new Remote.Service.WebService();
for(int i=0;i<20;i++){
byte[] image = instance.GetImageData ("fileName",i );
//save the file in external media
if(IsExternalMediaAvailable ()){
Java.IO.File path = new Java.IO.File ((Android.OS.Environment.ExternalStorageDirectory.Path+"/TestFolder/").Replace ("//", "/"));
Java.IO.File file = new Java.IO.File (path, i+fileName);
try {
path.Mkdirs ();
try {
FileOutputStream oStream = new FileOutputStream (file);
oStream.Write (data, 0, data.Length);
oStream.Close ();				
} catch (Exception ex) {
Android.Util.Log.Warn (TAG, ex.StackTrace + "\n" + ex.Message + "\n" + ex.InnerException);
}
}
}
service.Dispose();


		}

		protected override void OnPreExecute ()
		{
			base.OnPreExecute ();


		}

		protected override void OnPostExecute (string result)
		{

				
			base.OnPostExecute (result);
		}

		protected override void OnProgressUpdate (params string[] values)
		{
			base.OnProgressUpdate (values);		
		}

public bool IsExternalMediaAvailable ()
{
bool mExternalStorageAvailable = false;
bool mExternalStorageWriteable = false;
string state = Android.OS.Environment.ExternalStorageState;
if (Android.OS.Environment.MediaMounted == state) {
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Android.OS.Environment.MediaMountedReadOnly == (state)) {
// We can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
return mExternalStorageAvailable && mExternalStorageWriteable;
}
	}
Comment 5 Atsushi Eno 2012-09-24 03:15:28 UTC
Created attachment 2605 [details]
example case that I couldn't reproduce with.

Based on your code I tried to reproduce the issue, but I couldn't. I disabled these lines:
- instance.GetImageData ("fileName", i);
- Remote.Service.WebService service = new Remote.Service.WebService();

so they likely caused the actual issue. Could you provide some missing bits that is enough to reproduce the issue? (Or if you could reproduce the issue only my code just let us know) Thanks for the help.
Comment 6 Surya Prakash 2012-09-25 00:06:44 UTC
The GetImageData is a webmethod developed using c# and it returns approx 10kb to 2mb of data in a single bit stream, and also the error occurred when the async class was called in a loop of range greater than 20.
Comment 7 Surya Prakash 2012-10-06 06:03:43 UTC
Also this error occurs at random while using even simple AsyncTasks.

And when I did some research into this bug, I got an answer saying that it might be possible because of JNI Local Reference Changes in ICS (http://android-developers.blogspot.ie/2011/11/jni-local-reference-changes-in-ics.html). So, Could you please provide some insight regarding this. Or would there be an update in the next version of the monodroid ?
Comment 8 Jonathan Pryor 2012-10-08 16:51:35 UTC
We're still unable to reproduce this. If you could please attach a test case along with repro instructions, or take the test case attached to Comment #5 and modify it so that it fails, we would appreciate it.

This is not a bug due to JNI local reference changes, because the error you're reporting is regarding the global reference table, not the local reference table:

> E/dalvikvm( 4797): JNI ERROR (app bug): accessed stale global reference 0x1d400716 (index 453 in a table of size 453)

The managed stack trace is largely ignorable, actually: once Dalvik encounters a JNI error, the ~next call into Dalvik will destroy the process. In this case it just "happens" to be in AsyncTask<,,> (perhaps because you're reliably/consistently triggering the JNI error with AsyncTask<,,>?).

If you're able to easily & quickly reproduce this error, what you can instead do is enable gref logging then restart your app until it crashes. The gref logging output will list every gref created and destroyed, allowing you (us, if you attach the log file) to determine where the stale gref was created:

    http://docs.xamarin.com/android/advanced_topics/diagnostics
    adb shell setprop debug.mono.log gref

Gref logging output will be written to logcat:

    http://docs.xamarin.com/android/advanced_topics/android_debug_log

Thanks,
 - Jon
Comment 9 Surya Prakash 2012-10-09 00:58:29 UTC
Created attachment 2715 [details]
Error Raised during the Freeze and crash of the application

Apologies.

I should have mentioned earlier that the application that was developed was working great in emulator, 

but the (Freezing and Crashing) happens only in live device which has Android OS version 4 and above 
and in the rest there is no such crashing.

I have attached a Error Compilation that occurred during the Freeze of the app.

Also since the app freezes at this state the android OS automatically shuts down the Application after a time delay of 5 secs until which no other keys in the device are accessible.

Since, this error occurs randomly, I don't have a test case or any other methods to reproduce the error, except the log files that I have got using alogcat app installed in the device.
Comment 10 Jonathan Pryor 2012-10-09 11:35:07 UTC
As mentioned in Comment #8, the problem is not immediately in AsyncTask; the problem is that your app is somehow accessing a gref after it was deleted:

> I/dalvikvm( 3204): JNI ERROR (app bug): accessed deleted global reference 0x1d500f9a

The question is _why_. Your Attachment #2715 [details] doesn't answer that question; enabling gref logging _can_, as the gref messages will indicate when e.g. gref 0x1d500f9a was deleted, e.g. a message like:

> -g- grefc 107 gwrefc 0 handle 0x1d500f9a/G from ...

Note: the actual value will vary from execution to execution. You'll need to enable gref logging, run your app and provoke a crash, find the current global reference value which is causing your app to crash, and then look backwards in the log to see where it was deleted.

See also:

http://docs.xamarin.com/android/advanced_topics/diagnostics#Global_Reference_Messages

For example, the following code will generate a _similar_ JNI error:

	var s = new Java.Lang.String ("foo");
	var h = s.Handle;
	s.Dispose();
	var s2 = Java.Lang.Object.GetObject<Java.Lang.String>(
			h, JniHandleOwnership.TransferGlobalRef);

This fails because we're using a gref handle after it's been disposed (as `s.Dispose()` will cause `s.Handle` to be deleted):

> E/dalvikvm( 9899): JNI ERROR (app bug): accessed stale global reference 0x1d200216 (index 133 in a table of size 133)
> E/dalvikvm( 9899): VM aborting
> I/mono    ( 9899): Stacktrace:
> I/mono    ( 9899): 
> I/mono    ( 9899):   at Android.Runtime.JNIEnv.<Initialize>m__85 (intptr) <IL 0x00006, 0x00017>
> I/mono    ( 9899):   at Java.Lang.Object.GetObject (intptr,Android.Runtime.JniHandleOwnership,System.Type) <IL 0x0002f, 0x000b7>
> I/mono    ( 9899):   at Java.Lang.Object._GetObject<T> (intptr,Android.Runtime.JniHandleOwnership) <IL 0x00026, 0x0004f>
> I/mono    ( 9899):   at Java.Lang.Object.GetObject<T> (intptr,Android.Runtime.JniHandleOwnership) <IL 0x00002, 0x0002b>
> I/mono    ( 9899):   at Scratch.ViewRotation.Activity1.OnCreate (Android.OS.Bundle) [0x000a9] in /Users/jon/Projects/Scratch.ViewRotation/Activity1.cs:40
> I/mono    ( 9899):   at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (intptr,intptr,intptr) <IL 0x00012, 0x00057>
> I/mono    ( 9899):   at (wrapper dynamic-method) object.eb097602-6fd9-4e35-95bc-64eb6522ad04 (intptr,intptr,intptr) <IL 0x00012, 0x00033>
> I/mono    ( 9899):   at (wrapper native-to-managed) object.eb097602-6fd9-4e35-95bc-64eb6522ad04 (intptr,intptr,intptr) <IL 0x0001f, 0xffffffff>

The bug you're seeing could be an app bug (you're deliberately disposing of an instance while still using it elsewhere) or a framework bug. Until we have full gref logs, it's impossible to say where the bug lies.
Comment 11 Surya Prakash 2012-10-13 00:41:40 UTC
Thanks I was able to get the gref logs of it and was able to fix the error