Bug 31338 - Getting INtPTRZero Error during Runtime
Summary: Getting INtPTRZero Error during Runtime
Status: CONFIRMED
Alias: None
Product: Android
Classification: Xamarin
Component: Mono runtime / AOT Compiler (show other bugs)
Version: 5.1
Hardware: PC Windows
: Normal normal
Target Milestone: ---
Assignee: marcos.henrich
URL:
Depends on:
Blocks:
 
Reported: 2015-06-24 02:12 UTC by Dharmender Sharma
Modified: 2017-06-29 17:47 UTC (History)
6 users (show)

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


Attachments

Description Dharmender Sharma 2015-06-24 02:12:53 UTC
Hi,

I am developing a gaming application which contains two single instance activities. I have a back and forth navigation, so I don't call finish method of activity while navigating from one activity to another. I spend most of the time in second activity which is my game activity. So when I come back to main activity, and click any of the view controls like button,check box or the image view. The App Crashes and shows following error

03-28 00:21:42.803 E/mono (30674): Unhandled Exception:
03-28 00:21:42.803 E/mono (30674): System.ArgumentException: 'jobject' must not be IntPtr.Zero.
03-28 00:21:42.803 E/mono (30674): Parameter name: jobject
03-28 00:21:42.803 E/mono (30674): at Android.Runtime.JNIEnv.CallVoidMethod (IntPtr jobject, IntPtr jmethod, 

My Client is really unsatisfied due to random crashes, And I checked the crash reports in xamarin insights. All I found is the above mentioned error. As I have to put this game in play store soon. And, I don't know how you will manage, I just want a fix to this issue immediately. I can't wait any more.
Comment 1 Dharmender Sharma 2015-06-24 02:29:19 UTC
Enviornment info:
Xamarin Studio
Version 5.9.3 (build 1)
Installation UUID: 1dce1499-0a79-45b9-b102-ce8159c74e03
Runtime:
	Microsoft .NET 4.0.30319.34014
	GTK+ 2.24.22 (MS-Windows theme)
	GTK# 2.12.26

Xamarin.Android
Version: 5.1.3 (Business Edition)
Android SDK: D:\Dharmbackup\SoftwareInstall\android-sdk\android-sdk
	Supported Android versions:
		2.3    (API level 10)
		4.0.3  (API level 15)
		4.1    (API level 16)
		4.2    (API level 17)
		4.3    (API level 18)
		4.4    (API level 19)
		4.4.87 (API level 20)
		5.0    (API level 21)
Java SDK: C:\Program Files\Java\jdk1.7.0_60
java version "1.7.0_60"
Java(TM) SE Runtime Environment (build 1.7.0_60-b19)
Java HotSpot(TM) 64-Bit Server VM (build 24.60-b09, mixed mode)

Xamarin Android Player
Not Installed

Build Information
Release ID: 509030001
Git revision: 5a524e1726ed103fdd4fe37e0356f2b35466ce9d
Build date: 2015-06-02 16:19:11-04
Xamarin addins: 51957cfbd06be911b212671ad05c2c6221ac90f9

Operating System
Windows 6.2.9200.0 (64-bit)
Comment 2 Dharmender Sharma 2015-06-24 02:33:45 UTC
The Client is not accepting the application. we have completed our development part and got stuck on this issue and not able to go ahead.
we have very tight deadline to fix this thing. please cooperate and give me a fix ASAP.
Comment 3 Dharmender Sharma 2015-06-24 02:43:20 UTC
The Client is not accepting the application. we have completed our development part and got stuck on this issue and not able to go ahead.
we have very tight deadline to fix this thing. please cooperate and give me a fix ASAP.
Comment 4 Jonathan Pryor 2015-06-24 13:23:22 UTC
All this means:

> 03-28 00:21:42.803 E/mono (30674): System.ArgumentException: 'jobject' must not be IntPtr.Zero.

is that you're trying to invoke a method on an instance which has been invalidated.

We don't know why the instance has been invalidated, or how to fix it, or anything else useful.

Please attach a repro so that we can investigate.
Comment 6 Dharmender Sharma 2015-06-25 01:50:20 UTC
I've attached the source code . please have a look at it.
Comment 8 Dharmender Sharma 2015-06-29 10:01:24 UTC
06-29 19:29:26.049  17352-17352/com.gaussnetworks.monopoker E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.gaussnetworks.monopoker, PID: 17352
    java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.reflect.InvocationTargetException
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: md52ce486a14f4bcd95899665e9d932190b.JavaProxyThrowable: System.ArgumentException: 'jobject' must not be IntPtr.Zero.
    Parameter name: jobject
            at Android.Runtime.JNIEnv.CallVoidMethod (intptr,intptr,Android.Runtime.JValue*) <0x0013c>
            at Android.App.Activity.RunOnUiThread (Java.Lang.IRunnable) <0x00137>
            at Android.App.Activity.RunOnUiThread (System.Action) <0x00033>
            at MonoPoker.MainActivity.HideNavigationDrawer () <0x0009f>
            at MonoPoker.MainActivity.<imgRetryFailedAlertButtonOK_Click>b__54 () <0x0005f>
            at Java.Lang.Thread/RunnableImplementor.Run () <0x0003f>
            at Java.Lang.IRunnableInvoker.n_Run (intptr,intptr) <0x0003b>
            at (wrapper dynamic-method) object.ac35fb0f-e295-42b4-955e-9a1578e4ad4a (intptr,intptr) <0x0003b>
            at mono.java.lang.RunnableImplementor.n_run(Native Method)
            at mono.java.lang.RunnableImplementor.run(RunnableImplementor.java:29)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5086)
Comment 9 Jonathan Pryor 2015-07-06 17:07:10 UTC
Thank you for the the complete call stack.

This is the important bit:

>      Caused by: md52ce486a14f4bcd95899665e9d932190b.JavaProxyThrowable: System.ArgumentException: 'jobject' must not be IntPtr.Zero.
>     Parameter name: jobject
>             at Android.Runtime.JNIEnv.CallVoidMethod (intptr,intptr,Android.Runtime.JValue*) <0x0013c>
>             at Android.App.Activity.RunOnUiThread (Java.Lang.IRunnable) <0x00137>
>             at Android.App.Activity.RunOnUiThread (System.Action) <0x00033>
>             at MonoPoker.MainActivity.HideNavigationDrawer () <0x0009f>

The probable cause for this is that `this.Handle` is IntPtr.Zero, i.e. there is no valid handle to the Java peer.

This makes no sense. :-(

What does GameApplication do? Does it ever call Dispose() on the MainActivity?

Furthermore, there's this method on the callstack:

>             at MonoPoker.MainActivity.HideNavigationDrawer () <0x0009f>
>             at MonoPoker.MainActivity.<imgRetryFailedAlertButtonOK_Click>b__54 () <0x0005f>

This likewise makes no sense; *usually*, by compiler convention, the name of a compiler-generated anonymous method contains includes the field + event you're assigning to. For example, based on `<imgRetryFailedAlertButtonOK_Click>b__54 ()`, I'd expect the source code to at least *mention* imgRetryFailedAlertButtonOK, e.g.:

    imgRetryFailedAlertButtonOK.Click += (o, e) => {/* ... */};

Yet there is no reference to "imgRetry", or "Retry", within Attachment #11733 [details].

Finally, this may have nothing to do with your issue, but maintaining static references to Activity instances is usually bad form:

>             GameApplication.Current.MainActivity = this;

The reason for this is that it can result in memory "leaks"

http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html

Care should be taken when storing Context subclasses such as Activities (or Services, or...) into static variables.
Comment 11 Jonathan Pryor 2015-08-19 10:33:06 UTC
Wow, is that subtle.

> We have a rather useless stack trace for *a lot* of errors:

Stack traces are rarely useless. :-)

At least, this one isn't, and shows what the "subtle" issue is.

For some related background:

http://forums.xamarin.com/discussion/38199/post-action-postdelayed-action-and-removecallbacks-action-dont-behave-as-expected

TL;DR: In order to support Handler.RemoveCallbacks(Action) and similar methods, we internally maintain a Dictionary<Action, IRunnable> so that we can properly unregister the correct IRunnable instance given an Action. (There's some bugginess there which the above thread goes into.)

Dictionary<Action, IRunnable> in turn hits Action.GetHashCode() for lookup, and if Action.Target is not null, then Action.Target.GetHashCode() is invoked as part of getting Action.GetHashCode():

https://github.com/mono/mono/blob/mono-4.0.0-branch/mcs/class/corlib/System/Delegate.cs#L502

This background is correlated by the "useless" stack trace:

> at Android.Runtime.JNIEnv.CallNonvirtualIntMethod (intptr,intptr,intptr) <0x0019c>
> at Java.Lang.Object.GetHashCode () <0x0010b>
> at System.Delegate.GetHashCode () <0x00047>
> at System.MulticastDelegate.GetHashCode () <0x00013>
> at System.Collections.Generic.DefaultComparer`1<System.Action>.GetHashCode (System.Action) x00037>
> at System.Collections.Generic.Dictionary`2<System.Action, Java.Lang.Thread/RunnableImplementor>.Remove (System.Action) <0x0006b>
> at Java.Lang.Thread/RunnableImplementor.Run () <0x0008f>
> at Java.Lang.IRunnableInvoker.n_Run (intptr,intptr) <0x0003b>
> at (wrapper dynamic-method) object.ab61efd0-ee75-4c3a-8eba-bfde1c7c0e76 (intptr,intptr) <0x0003b>

However, this also shows the problem: the whole reason we're hitting Java.Lang.Object.GetHashCode() is because Action.Target is non-null, meaning the delegate is an instance method.

Thus, if we return to your original method:

> this._scrollView.Post(() => this._scrollView.ScrollTo(0, this._fragment.CurrentScrollOffset));

The compiler turns the delegate into an *instance* method on the local type:

  this._scrollView.Post(__compiler_InstanceMethod);
  ...
  void __compiler_InstanceMethod ()
  {
    this._scrollView.ScrollTo(0, this._fragment.CurrentScrollOffset);
  }

When you introduce the temporary and no longer use `this` within the lambda:

> var item = this;
> this._scrollView.Post(() => item._scrollView.ScrollTo(0, item._fragment.CurrentScrollOffset));

the compiler doesn't introduce a new instance method on the current type. Instead, it generates a new type for the closure, and that new type won't inherit Java.Lang.Object:

    class __compiler_Closure {
        public YourType $item;
        public void __Post ()
        {
            $item._scrollView.ScrollTo(0, $item._fragment.CurrentScrollOffset);
        }
    }
    ...
    var __closure = new __compiler_Closure {
        $item = this;
    };
    this._scrollView.Post(__closure.__Post);

This very subtle change allows our Dictionary<Action, IRunnable> lookup to work without the Java.Lang.Object.GetHashCode() invocation, avoiding the exception.

Subtle subtle subtle.

Which raises a few issues:

1. Xamarin should check Action.Target before the lookup to avoid invoking Object.GetHashCode() on an invalid instance.

2. The reason it's throwing because your Fragment was being invalidated after your Post()ed Action was invoked but *before* we call Dictionary`2.Remove(). (The Action is invoked first; if `this` were invalidated, then the callback would have thrown before we call Dictionary`2.Remove(). This implies that the instance is invalidated afterward, which doesn't make any sense at all and seems like a hell of a timing issue.)

I have no idea how or why (2) is happening, but I can't think of anything else that would explain the stack trace.
Comment 12 Jonathan Pryor 2015-08-19 12:35:39 UTC
The problem with (1) is that there's then no way to remove entries from the Dictionary, which would thus be a memory leak. :-(

A better idea may be to change Delegate.GetHashCode() to do what .NET does, and *not* call Delegate.Target.GetHashCode():

https://github.com/mono/referencesource/blob/679deadc4e5c07093087c8ce3c99d74b76b3d33e/mscorlib/system/delegate.cs#L188-L201
Comment 13 Geir Ludvigsen 2015-11-12 03:28:14 UTC
One of our customers have also bumped into this problem:

Android 4.4.2
samsung - GT-P5210
Xamarin.Android 4.20.0.34

ArgumentException: 'jobject' must not be IntPtr.Zero.Parameter name: jobject
at Android.Runtime.JNIEnv.CallNonvirtualIntMethod (intptr,intptr,intptr) <0x001ab>
at Java.Lang.Object.GetHashCode () <0x000e7>
at System.Delegate.GetHashCode () <0x00031>
at System.MulticastDelegate.GetHashCode () <0x00013>
at System.Collections.Generic.DefaultComparer`1<System.Action>.GetHashCode (System.Action) <0x0001c>
at System.Collections.Generic.Dictionary`2<System.Action, Java.Lang.Thread/RunnableImplementor>.Remove (System.Action) <0x0003f>
at Java.Lang.Thread/RunnableImplementor.Run () <0x0006f>
at Java.Lang.IRunnableInvoker.n_Run (intptr,intptr) <0x0002c>
at (wrapper dynamic-method) object.deb7084b-8954-4dd8-981c-2db22fdace98 (intptr,intptr) <0x0001b>

I didn't quite get any conclusions from above comments: Should we work around the problem somehow in our code or must we wait for new Xamarin version?

Any updates on this from Xamarin are appreciated.
Comment 14 Jon Douglas [MSFT] 2017-06-29 17:47:13 UTC
I am CONFIRMING this issue based on the comments back and forth regarding potential solutions to this issue. If this has already been fixed, please feel free to RESOLVE this. If anyone in the meantime would like to submit a reproduction project, feel free to upload this to the bugzilla bug directly.

Note You need to log in before you can comment on or make changes to this bug.