Commit 101fea2
authored
[illink] Redo Java.Lang.Object serialization (#5473)
Context: #5454
The use of `DataContract` attribute on `Java.Lang.Object` class pulls
in `System.Runtime.Serialization.Primitives` assembly.
We still need to make the `Java.Lang.Object` class serializable, so that
inherited types can be serialized. Otherwise that would lead to
`System.Runtime.Serialization.InvalidDataContractException` during
runtime.
Instead of decorating `Java.Lang.Object` with `DataContract` attribute,
use `Serializable` attribute on class and `NonSerialized` attribute on fields.
This might seem contraproductive, to use multiple attribute instances
instead of one. In real it is not and leads to size saving and getting rid
of `System.Runtime.Serialization.Primitives` assembly reference
in linked apps. Because the `Serializable` and `NonSerialized` attributes
are not present in the compiled output, instead flags are used.
The compiled `Java.Lang.Object` class IL looks like this:
```
.class public auto ansi serializable beforefieldinit Java.Lang.Object
extends [System.Private.CoreLib]System.Object
implements [System.Private.CoreLib]System.IDisposable,
Android.Runtime.IJavaObject,
Java.Interop.IJavaObjectEx,
[Java.Interop]Java.Interop.IJavaPeerable
{
.custom instance void Android.Runtime.RegisterAttribute::.ctor(string) = ( 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A // ...java/lang/Obj
65 63 74 01 00 54 02 10 44 6F 4E 6F 74 47 65 6E // ect..T..DoNotGen
65 72 61 74 65 41 63 77 01 ) // erateAcw.
.field private static initonly class [Java.Interop]Java.Interop.JniPeerMembers _members
.field private static class [System.Private.CoreLib]System.Delegate cb_equals_Ljava_lang_Object_
.field private static class [System.Private.CoreLib]System.Delegate cb_hashCode
.field private static class [System.Private.CoreLib]System.Delegate cb_toString
.field private notserialized native int key_handle
.field private notserialized native int weak_handle
.field private notserialized int32 refs_added
.field private notserialized valuetype Android.Runtime.JObjectRefType handle_type
.field private notserialized native int handle
.field private notserialized bool needsActivation
.field private notserialized bool isProxy
...
```
The apk size savings on net6 in BuildReleaseArm64False test:
```
> apkdiff -md -e dll$ before.apk after.apk
Size difference in bytes ([*1] apk1 only, [*2] apk2 only):
- 13 assemblies/Mono.Android.dll
- 120 Metadata
- 60 Stream #~ (tables)
- 6 Table TypeRef
- 6 Table MemberRef
- 6 Table CustomAttribute
- 40 Table AssemblyRef
- 60 Stream #Strings
Type Java.Lang.Object
- CustomAttribute System.Runtime.Serialization.DataContractAttribute
- 2,583 assemblies/System.Runtime.Serialization.Primitives.dll *1
Summary:
- 2,596 Assemblies -0.28% (of 915,384)
```
I have also added a new test for `Java.Lang.Object` class serialization with code from
old `Hello` sample.
Example of `System.Runtime.Serialization.InvalidDataContractException` during runtime,
if `Java.Lang.Object` class was not serializable:
```
I MonoDroid: Android.Runtime.JavaProxyThrowable: Exception of type 'Android.Runtime.JavaProxyThrowable' was thrown.
I MonoDroid: --- End of managed Android.Runtime.JavaProxyThrowable stack trace ---
I MonoDroid: android.runtime.JavaProxyThrowable: System.Runtime.Serialization.InvalidDataContractException: Type 'UnnamedProject.Person' cannot inherit from a type that is not marked with DataContractAttribute or SerializableAttribute. Consider marking the base type 'Java.Lang.Object' with DataContractAttribute or SerializableAttribute, or removing them from the derived type.
I MonoDroid: at System.Runtime.Serialization.ClassDataContract+ClassDataContractCriticalHelper..ctor (System.Type type) [0x001c3] in <686be187480b41979dcbf5635f805a7b>:0
I MonoDroid: at System.Runtime.Serialization.ClassDataContract..ctor (System.Type type) [0x00000] in <686be187480b41979dcbf5635f805a7b>:0
I MonoDroid: at System.Runtime.Serialization.DataContract+DataContractCriticalHelper.CreateDataContract (System.Int32 id, System.RuntimeTypeHandle typeHandle, System.Type type) [0x000e0] in <686be187480b41979dcbf5635f805a7b>:0
I MonoDroid: at System.Runtime.Serialization.DataContract+DataContractCriticalHelper.GetDataContractSkipValidation (System.Int32 id, System.RuntimeTypeHandle typeHandle, System.Type type) [0x0000b] in <686be187480b41979dcbf5635f805a7b>:0
I MonoDroid: at System.Runtime.Serialization.DataContract.GetDataContractSkipValidation (System.Int32 id, System.RuntimeTypeHandle typeHandle, System.Type type) [0x00000] in <686be187480b41979dcbf5635f805a7b>:0
I MonoDroid: at System.Runtime.Serialization.DataContract.GetDataContract (System.Int32 id, System.RuntimeTypeHandle typeHandle, System.Runtime.Serialization.SerializationMode mode) [0x00000] in <686be187480b41979dcbf5635f805a7b>:0
I MonoDroid: at System.Runtime.Serialization.DataContract.GetDataContract (System.RuntimeTypeHandle typeHandle, System.Type type, System.Runtime.Serialization.SerializationMode mode) [0x00006] in <686be187480b41979dcbf5635f805a7b>:0
I MonoDroid: at System.Runtime.Serialization.DataContract.GetDataContract (System.Type type) [0x00006] in <686be187480b41979dcbf5635f805a7b>:0
I MonoDroid: at System.Runtime.Serialization.Json.DataContractJsonSerializer.get_RootContract () [0x00022] in <686be187480b41979dcbf5635f805a7b>:0
I MonoDroid: at System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalWriteObjectContent (System.Runtime.Serialization.XmlWriterDelegator writer, System.Object graph) [0x00031] in <686be187480b41979dcbf5635f805a7b>:0
I MonoDroid: at System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalWriteObject (System.Runtime.Serialization.XmlWriterDelegator writer, System.Object graph) [0x00008] in <686be187480b41979dcbf5635f805a7b>:0
I MonoDroid: at System.Runtime.Serialization.XmlObjectSerializer.InternalWriteObject (System.Runtime.Serialization.XmlWriterDelegator writer, System.Object graph, System.Runtime.Serialization.DataContractResolver dataContractResolver) [0x00000] in <686be187480b41979dcbf5635f805a7b>:0
I MonoDroid: at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions (System.Runtime.Serialization.XmlWriterDelegator writer, System.Object graph, System.Runtime.Serialization.DataContractResolver dataContractResolver) [0x00073] in <686be187480b41979dcbf5635f805a7b>:0 01-07 16:13:09.246 10624 10624 I MonoDroid: at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions (System.Runtime.Serialization.XmlWriterDelegator writer, System.Object graph) [0x00000] in <686be187480b41979dcbf5635f805a7b>:0
I MonoDroid: at System.Runtime.Serialization.Json.DataContractJsonSerializer.WriteObject (System.Xml.XmlDictionaryWriter writer, System.Object graph) [0x0000d] in <686be187480b41979dcbf5635f805a7b>:0
I MonoDroid: at System.Runtime.Serialization.Json.DataContractJsonSerializer.WriteObject (System.IO.Stream stream, System.Object graph) [0x00018] in <686be187480b41979dcbf5635f805a7b>:0
I MonoDroid: at UnnamedProject.MainActivity.TestJsonDeserializationCreatesJavaHandle () [0x00033] in <11a2c65ab60d41dea720c7638d552ce0>:0
I MonoDroid: at UnnamedProject.MainActivity.OnCreate (Android.OS.Bundle bundle) [0x0004b] in <11a2c65ab60d41dea720c7638d552ce0>:0 01-07 16:13:09.247 10624 10624 I MonoDroid: at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00012] in <3045e86f0ced43c19ee1b522f77c72d7>:0
I MonoDroid: at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00012] in <3045e86f0ced43c19ee1b522f77c72d7>:0
I MonoDroid: at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.1(intptr,intptr,intptr)
I MonoDroid: at unnamedproject.unnamedproject.MainActivity.n_onCreate(Native Method)
I MonoDroid: at unnamedproject.unnamedproject.MainActivity.onCreate(MainActivity.java:29)
I MonoDroid: at android.app.Activity.performCreate(Activity.java:8000)
I MonoDroid: at android.app.Activity.performCreate(Activity.java:7984)
I MonoDroid: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
I MonoDroid: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3404)
I MonoDroid: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595)
I MonoDroid: at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
I MonoDroid: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
I MonoDroid: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
I MonoDroid: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
I MonoDroid: at android.os.Handler.dispatchMessage(Handler.java:106)
I MonoDroid: at android.os.Looper.loop(Looper.java:223)
I MonoDroid: at android.app.ActivityThread.main(ActivityThread.java:7660)
I MonoDroid: at java.lang.reflect.Method.invoke(Native Method)
I MonoDroid: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
I MonoDroid: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
I MonoDroid:
W ActivityTaskManager: Force finishing activity UnnamedProject.UnnamedProject/unnamedproject.unnamedproject.MainActivity
```1 parent 597e716 commit 101fea2
File tree
5 files changed
+80
-10
lines changed- src
- Mono.Android/Java.Lang
- Xamarin.Android.Build.Tasks/Tests
- Xamarin.Android.Build.Tests
- Xamarin.ProjectTools/Resources/Base
- tests
- MSBuildDeviceIntegration/Tests
- api-compatibility
5 files changed
+80
-10
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
15 | | - | |
| 15 | + | |
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
| 21 | + | |
22 | 22 | | |
23 | | - | |
24 | | - | |
| 23 | + | |
| 24 | + | |
25 | 25 | | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| |||
Lines changed: 0 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
89 | 89 | | |
90 | 90 | | |
91 | 91 | | |
92 | | - | |
93 | 92 | | |
94 | 93 | | |
95 | 94 | | |
| |||
103 | 102 | | |
104 | 103 | | |
105 | 104 | | |
106 | | - | |
107 | 105 | | |
108 | 106 | | |
109 | 107 | | |
| |||
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
35 | 36 | | |
36 | 37 | | |
37 | 38 | | |
Lines changed: 70 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
419 | 419 | | |
420 | 420 | | |
421 | 421 | | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
422 | 492 | | |
423 | 493 | | |
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| 25 | + | |
0 commit comments