Bug 22912 - DateTime.Now gives NullReferenceException in other AppDomain
Summary: DateTime.Now gives NullReferenceException in other AppDomain
Status: RESOLVED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: Mono runtime / AOT Compiler ()
Version: 4.18.0
Hardware: PC Windows
: Normal normal
Target Milestone: 5.1
Assignee: Jonathan Pryor
URL:
Depends on:
Blocks:
 
Reported: 2014-09-12 06:12 UTC by Neil Boyd
Modified: 2015-02-02 12:49 UTC (History)
5 users (show)

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


Attachments
Demo app (14.46 KB, application/octet-stream)
2014-09-12 06:12 UTC, Neil Boyd
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 Neil Boyd 2014-09-12 06:12:31 UTC
Created attachment 8021 [details]
Demo app

When I call DateTime.Now in a secondary AppDomain I get a NullReferenceException.

I have attached a simple example app to demonstrate this.

This may be related to the fix to bug 4902.
Comment 1 Neil Boyd 2014-09-12 07:21:54 UTC
This bug occurs in version 3.5.55 and 3.5.58, but not in 3.3.47
Comment 2 Jonathan Pryor 2014-09-12 09:34:22 UTC
The stack trace for the NullReferenceException:

> I/mono-stdout(23168): ************************************** now exception: System.NullReferenceException: Object reference not set to an instance of an object
> I/mono-stdout(23168):   at Android.Runtime.JNIEnv.SetEnv () [0x00000] in <filename unknown>:0 
> I/mono-stdout(23168):   at Android.Runtime.JNIEnv.get_Handle () [0x00000] in <filename unknown>:0 
> I/mono-stdout(23168):   at Android.Runtime.JNIEnv.get_Env () [0x00000] in <filename unknown>:0 
> I/mono-stdout(23168):   at Android.Runtime.JNIEnv.NewString (System.Char[] text, Int32 length) [0x00000] in <filename unknown>:0 
> I/mono-stdout(23168):   at Android.Runtime.JNIEnv.BinaryName (System.String classname) [0x00000] in <filename unknown>:0 
> I/mono-stdout(23168):   at Android.Runtime.JNIEnv.FindClass (System.String classname) [0x00000] in <filename unknown>:0 
> I/mono-stdout(23168):   at Android.Runtime.JNIEnv.FindClass (System.String className, System.IntPtr& cachedJniClassHandle) [0x00000] in <filename unknown>:0 
> I/mono-stdout(23168):   at Java.Util.TimeZone.get_class_ref () [0x00000] in <filename unknown>:0 
> I/mono-stdout(23168):   at Java.Util.TimeZone.get_Default () [0x00000] in <filename unknown>:0 
> I/mono-stdout(23168):   at Android.Runtime.AndroidCurrentSystemTimeZone..ctor () [0x00000] in <filename unknown>:0 
> I/mono-stdout(23168):   at Android.Runtime.AndroidEnvironment.GetCurrentSystemTimeZone () [0x00000] in <filename unknown>:0 
> I/mono-stdout(23168):   at System.AndroidPlatform.GetCurrentSystemTimeZone () [0x00000] in <filename unknown>:0 
> I/mono-stdout(23168):   at System.TimeZone.get_CurrentTimeZone () [0x00000] in <filename unknown>:0 
> I/mono-stdout(23168):   at System.DateTime.get_Now () [0x00000] in <filename unknown>:0 
> I/mono-stdout(23168):   at Other.Boom.Bang () [0x00000] in <filename unknown>:0 

The suggestion that this is related to Bug #4902 is correct. The problem is the fix. :-/

Background: Xamarin.Android wasn't designed with multiple AppDomains in mind (oops). Consequently, JNIEnv.Handle is IntPtr.Zero outside of the default AppDomain, and accessing it will result in the above NullReferenceException, because the internal JNIInvokeInterface instance hasn't been initialized for the non-default AppDomain, preventing us from obtaining the JNIEnv* for the current thread within the non-default AppDomain.

http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/invocation.html#GetEnv

The reason why Bug #4902 breaks things is visible from the above stack trace: DateTime.Now calls TimeZone.CurrentTimeZone, which uses Java.Util.TimeZone to determine the current timezone. This in turn requires a Java invocation, but the core information needed to perform Java invocations hasn't been initialized for the non-default AppDomain, and things fall apart from there.

That said, the pre-#4902 behavior was broken, in that the timezone obtained within the non-default AppDomain may not have been the correct timezone.
Comment 3 Neil Boyd 2014-09-12 10:38:05 UTC
I can't confirm this now because I went back to the older Xamarin, but as I remember, if you remove the override of InitializeLifetimeService then the exception occurs when you call CreateInstanceAndUnwrap.
Comment 4 Sadik Ali 2014-10-29 06:46:33 UTC
We have checked this issue and able to reproduce it with the help of bug description.

Screencast regarding Same:
http://www.screencast.com/t/LN9wOQ5ET2

Environment Info:
Microsoft Visual Studio Professional 2013
Version 12.0.30723.00 Update 3
Microsoft .NET Framework
Version 4.5.51641

Installed Version: Professional

Xamarin   3.7.230.0 (e78d10d6993f95fc3ebe791aeb4aacff165bf8bb)
Visual Studio extension to enable development for Xamarin.iOS and Xamarin.Android.

Xamarin.Android   4.18.0.39 (0ef616ae42005ece52f6df7aa1e093ceb11998f8)
Visual Studio plugin to enable development for Xamarin.Android.

Xamarin.iOS   8.4.0.0 (209abebbd8f1a292d042420edb45fa5fbd3f017b)
Visual Studio extension to enable development for Xamarin.iOS.
Comment 5 Jonathan Pryor 2014-11-03 16:21:58 UTC
This is (kinda-sorta) fixed via monodroid/f60c21c0 / Bug #23405 SO LONG AS the target Android device provides the persist.sys.timezone system property; see also Bug #4902.

So if you happen to be fortunate enough to have an Android target which sets the persist.sys.timezone property, then you should be able to use DateTime.Now from a secondary AppDomain without a problem in 4.18.1.

If you're not that fortunate, then it'll still blow up on you, just with a different stack trace.
Comment 6 Jonathan Pryor 2014-11-21 12:36:16 UTC
Support for devices which don't have the persist.sys.timezone system property was added in monodroid/b297364d.