Bug 15542 - Android template throws "Java.Lang.CloneNotSupportedException: Class doesn't implement Cloneable" on API 10 Emulator
Summary: Android template throws "Java.Lang.CloneNotSupportedException: Class doesn't ...
Status: VERIFIED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: General (show other bugs)
Version: 4.10.0.x
Hardware: All All
: High critical
Target Milestone: 4.10.1 (VS2013)
Assignee: Jonathan Pryor
URL:
: 15829 15879 (view as bug list)
Depends on:
Blocks:
 
Reported: 2013-10-21 09:31 UTC by Atin
Modified: 2013-11-05 11:57 UTC (History)
6 users (show)

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


Attachments

Description Atin 2013-10-21 09:31:34 UTC
Steps to reproduce:
1 Open XS.
2 Create a MFA template
3 Debug or run the application
4 Deploy application on API 10 Emulator

Actual result:
Observe that application throws "Java.Lang.CloneNotSupportedException: Class doesn't implement Cloneable". However application run successfully on above API-10 Emulator like Api-15, Api-17, Api-18

Screen cast:  http://screencast.com/t/PiqmRUBSYf0a

Supplement info: 
Android log: https://gist.github.com/atin360/1f1e014ac4042b2601a0
Application output: https://gist.github.com/atin360/6cf9fa35967dfc9cdb70

Expected result:
Application should run successfully on API 10 Emulator.

Environment info:
Mac Lion 10.7.5 
Windows 8
XS 4.1.7(build 1537)- dbd1c0e5959a2e590aefa16357c85f5514f56e6e
MFA 4.10.01004
Mono 3.2.4 ((no/f163333)

Regression status: REGRESSION, This is working fine with stable MFA 4.8.3-15
Comment 1 Peter Collins 2013-10-21 12:52:28 UTC
I'm able to reproduce this, here's some more logcat information:
https://gist.github.com/pjcollins/553e79b92939c87c76c4

OSX 10.9 (Mavericks GM Seed)
Mono 3.2.3 ((no/8d3b4b7)
XS 4.0.13
XA 4.10.1-4 / 25ee86bf
Samsung Galaxy Mini v2.3.4
Comment 2 Jonathan Pryor 2013-10-22 21:48:30 UTC
@Peter: Can you wrap the relevant code within a try/catch and print the stacktrace with Console.WriteLine()? That should show more of the stack.
Comment 3 Peter Collins 2013-10-28 16:35:58 UTC
I was able to reproduce with the latest from 4.10.1 lane (287c5d96)

caught and printed the exception here:
https://gist.github.com/pjcollins/553e79b92939c87c76c4
Comment 4 Peter Collins 2013-10-28 16:36:40 UTC
Make that https://gist.github.com/pjcollins/d8c26b91d668d96f0858
Comment 5 Jonathan Pryor 2013-10-28 17:07:12 UTC
For some reason, Activity.OnCreate() is calling Object.clone():

> W/System.err(  613): java.lang.CloneNotSupportedException: Class doesn't implement Cloneable
> W/System.err(  613):    at java.lang.Object.clone(Object.java:155)
> W/System.err(  613):    at scratch.bxc15542.MainActivity.n_onCreate(Native Method)
> W/System.err(  613):    at scratch.bxc15542.MainActivity.onCreate(MainActivity.java:28)
> W/System.err(  613):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
> W/System.err(  613):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
> W/System.err(  613):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
> W/System.err(  613):    at android.app.ActivityThread.access$1500(ActivityThread.java:117)
> W/System.err(  613):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
> W/System.err(  613):    at android.os.Handler.dispatchMessage(Handler.java:99)
> W/System.err(  613):    at android.os.Looper.loop(Looper.java:123)
> W/System.err(  613):    at android.app.ActivityThread.main(ActivityThread.java:3683)
> W/System.err(  613):    at java.lang.reflect.Method.invokeNative(Native Method)
> W/System.err(  613):    at java.lang.reflect.Method.invoke(Method.java:507)
> W/System.err(  613):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
> W/System.err(  613):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)

This makes no sense at all. :-(
Comment 6 Jonathan Pryor 2013-10-28 21:19:16 UTC
I have a repro:

	Log.Info ("*jonp*", "#Getting class...");
	var grefC = JNIEnv.FindClass ("mono/android/view/View_OnClickListenerImplementor");
	Log.Info ("*jonp*", "grefC=0x{0}", grefC.ToString ("x"));
	var lrefI = JNIEnv.CreateInstance (grefC, "()V");
	Log.Info ("*jonp*", "NewObject=0x{0}", lrefI.ToString ("x"));
	JNIEnv.DeleteLocalRef (lrefI);
	lrefI = JNIEnv.AllocObject (grefC);
	Log.Info ("*jonp*", "AllocObject=0x{0}", lrefI.ToString ("x"));
	Log.Info ("*jonp*", "before InvokeConstructor");
	JNIEnv.InvokeConstructor (lrefI, "()V");
	Log.Info ("*jonp*", " after InvokeConstructor");
	JNIEnv.DeleteLocalRef (lrefI);

There are now two ways to create Java instances:

JNIEnv.NewObject()
JNIEnv.AllocObject() + JNIEnv.CallVoidMethod()

JNIEnv.NewObject() works, and is what we've always done.

JNIEnv.AllocObject() + JNIEnv.CallVoidMethod() is the new approach introduced with Bug #14999, and apparently API-10 does NOT like this combination.

@PeterC: does this happen on any API-levels _before_ API-10? Or is this just the odd-man out?
Comment 7 Jonathan Pryor 2013-10-28 21:46:39 UTC
Modifying mono/android/view/View_OnClickListenerImplementor so that it does implement Java.Lang.ICloneable _does_ allow the AllocObject()+CallVoidMethod() construction to work.

I'm still trying to figure out _why_ java.lang.Cloneable is required on API-10. Weird bug.
Comment 8 Jonathan Pryor 2013-10-28 22:45:55 UTC
Why? Android bug, of course!

https://code.google.com/p/android/issues/detail?id=13832

Using JNIEnv.CallNonvirtualVoidMethod() instead of JNIEnv.CallVoidMethod() doesn't make any difference to workaround the Dalvik bug.

Which raises a wonderful question: how to fix this without regressing Bug #14999?

1. Undo Bug #14999's fix, and use some alternate mechanism/hack. We can use JNIEnv.AllocObject()+JNIEnv.CallVoidMethod() when we can drop < API-10 (< API-14?) support. (In...2-4 years?)

2. Modify ACW generation logic so that java.lang.Cloneable is _always_ implemented. This seems incredibly stupid, but it does appear to fix things. (It would need to be _all_ ACWs, as this same issue impacts user code, e.g. `class Demo : Java.Lang.Object {}` and `new Demo()` will blow up.)

I don't like (1). I don't know if (2) will "leak" anywhere, and may need additional checks of some form.
Comment 9 Jonathan Pryor 2013-10-29 21:11:22 UTC
Fixed in master/940136eb and monodroid-4.10.1-branch/33fffb02.

I rejected Comment #8 (1), as it's ebil, and (2) doesn't work (creating a java.lang.String with AllocObject()+CallVoidMethod() results in the same CloneNotSupportedException.

Further investigation (thanks PeterC!) shows that the Dalvik bug was fixed in Honeycomb, so pre-Honeycomb (including API-11) requires the pre-XA 4.10 use of NewObject()/CreateInstance().

Post-Honeycomb, meanwhile, can use AllocObject()+CallVoidMethod(), which has the added semantic cleanup that the (IntPtr, JniHandleOwnership) constructor is now almost never needed (except to subclass Application & Instrumentation). I didn't want to lose this or delay it 2-4 years (or whenever we can drop support for pre-Honeycomb platforms).

The chosen solution is to introduce JNIEnv.StartCreateInstance() and JNIEnv.FinishCreateInstance() method sets.

On Honeycomb+, StartCreateInstance() is AllocObject(), and FinishCreateInstance() is JNIEnv.CallVoidMethod().

Pre-Honeycomb, StartCreateInstance() is NewObject(), and FinishCreateInstance() is a no-op. Pre-Honeycomb thus doesn't get the the semantic cleanup.
Comment 10 Jonathan Pryor 2013-10-30 15:11:53 UTC
*** Bug 15829 has been marked as a duplicate of this bug. ***
Comment 11 Jonathan Pryor 2013-10-31 11:35:45 UTC
*** Bug 15829 has been marked as a duplicate of this bug. ***
Comment 12 Jonathan Pryor 2013-11-01 13:37:30 UTC
*** Bug 15879 has been marked as a duplicate of this bug. ***
Comment 13 Saurabh 2013-11-05 11:57:51 UTC
Today, we have check this issue with latest builds:

Mac and Windows
XS 4.1.13 (build 21)
mono-android-4.10.1-45

Now,we are able to deploy android template on API 10 emulator.

Hence, closing this issue.

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