Commit cec9eb4
[linker] Improve *Invoker types linking (#3525)
Fixes: #3454
Context: #3525 (comment)
Improves fix of #3263
The fix in commit
4d8c28f
increased the apk size more than needed. It marked all the
`*Invoker` types, because the `MarkJavaObjects` substep iterates over
all `Java.Lang.Object` derived types, before all the linking.
Turned out that the original regression came from the linker
itself. The new linker optimization was introduced in
dotnet/linker@13ea158
and so the `ITextWatcher` interface was not marked anymore.
> Interfaces on a type will no longer be marked simply because the
> type is marked. Instead, marking of interfaces on types is deferred
> until that interface type is marked for some other reason.
Before the new optimization, the linker preserved these
interfaces (like `ITextWatcher`) when marking the types based on them
(like `AbsListView` or `ITextWatcherImplementor` in this case). That
also resulted in keeping the invoker interfaces in the assembly. The
above mentioned optimization changed that.
Now they were linked out, because the interfaces implementation
are only accessed (during app runtime) after the invoker type is
loaded by `Type.GetType(string,bool)` in the native members
registration process. The linker cannot know about that without XA
help during the linking. The result of `ITextWatcher` being linked
away is that the `ITeextWatcherInvoker` type was linked away too.
It is now fixed by overriding the
`MarkStep.ShouldMarkInterfaceImplementation()` method, which returns
true for registered interfaces. These interfaces are special for XA
in a way, that it can be, in some cases, reached only from Java side
and thus linker is unable to track the interface usage. It is
similar to how linker handles the COM interfaces.
The crash in Topeka sample:
System.TypeLoadException: Could not load type 'Android.Text.ITextWatcherInvoker' from assembly 'Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
at (wrapper managed-to-native) System.RuntimeTypeHandle.internal_from_name(string,System.Threading.StackCrawlMark&,System.Reflection.Assembly,bool,bool,bool)
at System.RuntimeTypeHandle.GetTypeByName (System.String typeName, System.Boolean throwOnError, System.Boolean ignoreCase, System.Boolean reflectionOnly, System.Threading.StackCrawlMark& stackMark, System.Boolean loadTypeFromPartialName)
at System.RuntimeType.GetType (System.String typeName, System.Boolean throwOnError, System.Boolean ignoreCase, System.Boolean reflectionOnly, System.Threading.StackCrawlMark& stackMark)
at System.Type.GetType (System.String typeName, System.Boolean throwOnError)
at Android.Runtime.AndroidTypeManager.RegisterNativeMembers (Java.Interop.JniType jniType, System.Type type, System.String methods)
at Android.Runtime.JNIEnv.RegisterJniNatives (System.IntPtr typeName_ptr, System.Int32 typeName_len, System.IntPtr jniClass, System.IntPtr methods_ptr, System.Int32 methods_len)
at (wrapper managed-to-native) Java.Interop.NativeMethods.java_interop_jnienv_call_static_object_method_a(intptr,intptr&,intptr,intptr,Java.Interop.JniArgumentValue*)
at Java.Interop.JniEnvironment+StaticMethods.CallStaticObjectMethod (Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args)
at Android.Runtime.JNIEnv.CallStaticObjectMethod (System.IntPtr jclass, System.IntPtr jmethod, Android.Runtime.JValue* parms)
at Android.Runtime.JNIEnv.CallStaticObjectMethod (System.IntPtr jclass, System.IntPtr jmethod, Android.Runtime.JValue[] parms)
at Android.Runtime.JNIEnv.FindClass (System.String classname)
at Android.Runtime.JNIEnv.AllocObject (System.String jniClassName)
at Android.Runtime.JNIEnv.StartCreateInstance (System.String jniClassName, System.String jniCtorSignature, Android.Runtime.JValue* constructorParameters)
at Android.Runtime.JNIEnv.StartCreateInstance (System.String jniClassName, System.String jniCtorSignature, Android.Runtime.JValue[] constructorParameters)
at Android.Text.TextWatcherImplementor..ctor (System.Object inst, System.EventHandler`1[TEventArgs] changed_handler, System.EventHandler`1[TEventArgs] before_handler, System.EventHandler`1[TEventArgs] after_handler)
at Android.Widget.TextView.add_TextChanged (System.EventHandler`1[TEventArgs] value)
at Topeka.Fragments.SignInFragment.InitContentViews (Android.Views.View view)
at Topeka.Fragments.SignInFragment.OnViewCreated (Android.Views.View view, Android.OS.Bundle savedInstanceState)
at Android.App.Fragment.n_OnViewCreated_Landroid_view_View_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_view, System.IntPtr native_savedInstanceState)
at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.9(intptr,intptr,intptr,intptr)
The comparison of apk sizes with original and this fix (Topeka sample,
which was also used as repro):
| Version | Size in bytes |
|----------------|--------------:|
| Before @4d8c28 | 21434941 |
| After @4d8c28 | 28242405 |
| This fix | 21638678 |
So the previous fix increased the apk size by around 6.5Mbytes, this
fix adds less than 199kbytes instead.1 parent ebd65c9 commit cec9eb4
File tree
3 files changed
+31
-6
lines changed- src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner
3 files changed
+31
-6
lines changedLines changed: 23 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
120 | 120 | | |
121 | 121 | | |
122 | 122 | | |
123 | | - | |
| 123 | + | |
124 | 124 | | |
125 | 125 | | |
126 | 126 | | |
127 | | - | |
| 127 | + | |
128 | 128 | | |
129 | 129 | | |
130 | | - | |
| 130 | + | |
131 | 131 | | |
132 | 132 | | |
133 | 133 | | |
| |||
138 | 138 | | |
139 | 139 | | |
140 | 140 | | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
141 | 160 | | |
142 | 161 | | |
143 | 162 | | |
| |||
150 | 169 | | |
151 | 170 | | |
152 | 171 | | |
153 | | - | |
| 172 | + | |
154 | 173 | | |
155 | 174 | | |
156 | 175 | | |
| |||
Lines changed: 0 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
192 | 192 | | |
193 | 193 | | |
194 | 194 | | |
195 | | - | |
196 | | - | |
197 | 195 | | |
198 | 196 | | |
199 | 197 | | |
| |||
Lines changed: 8 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
436 | 436 | | |
437 | 437 | | |
438 | 438 | | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
439 | 447 | | |
440 | 448 | | |
441 | 449 | | |
| |||
0 commit comments