Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[illink] Do not preserve IO stream adapter/invoker #5449

Merged
merged 1 commit into from
Jan 4, 2021

Conversation

radekdoulik
Copy link
Member

Context: #5206
Context: #5167

They are only accessed through CallbackCode class in M.A.Export with
reflection code, which ILLink is able to detect.

This change reduces the apk size in common situation, when M.A.Export is
not used.

apk size comparison, BuildReleaseArm64False test:

> apkdiff -f -e dll$ before.apk after.apk
Size difference in bytes ([*1] apk1 only, [*2] apk2 only):
  -          80 assemblies/System.Console.dll
  -         129 assemblies/Java.Interop.dll
  -       1,237 assemblies/System.Private.CoreLib.dll
  -       6,093 assemblies/Mono.Android.dll
Summary:
  -       7,539 Assemblies -1.01% (of 749,078)

Context: dotnet#5206
Context: dotnet#5167

They are only accessed through `CallbackCode` class in M.A.Export with
reflection code, which ILLink is able to detect.

This change reduces the apk size in common situation, when M.A.Export is
not used.

apk size comparison, BuildReleaseArm64False test:

    > apkdiff -f -e dll$ before.apk after.apk
    Size difference in bytes ([*1] apk1 only, [*2] apk2 only):
      -          80 assemblies/System.Console.dll
      -         129 assemblies/Java.Interop.dll
      -       1,237 assemblies/System.Private.CoreLib.dll
      -       6,093 assemblies/Mono.Android.dll
    Summary:
      -       7,539 Assemblies -1.01% (of 749,078)
@jonpryor jonpryor merged commit 051cad7 into dotnet:master Jan 4, 2021
jonathanpeppers added a commit to jonathanpeppers/xamarin-android that referenced this pull request Jan 27, 2022
…asses

Fixes: dotnet/maui#2246
Fixes: dotnet/maui#4262
Fixes: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1447865

Revert "[One .NET] Do not preserve IO stream adapter/invoker (dotnet#5449)"

This reverts commit 051cad7.

`dotnet new maui-blazor` crashes in Release mode with:

    Android.Runtime.JavaProxyThrowable: Exception_WasThrown, Android.Runtime.JavaProxyThrowable
    --- End of managed Android.Runtime.JavaProxyThrowable stack trace ---
    android.runtime.JavaProxyThrowable: System.ArgumentException: Arg_DlgtTargMeth
    at System.Delegate.CreateDelegate(Type , Type , String , Boolean , Boolean )
    at System.Delegate.CreateDelegate(Type , Type , String )
    at Android.Runtime.AndroidTypeManager.RegisterNativeMembers(JniType , Type , String )
    --- End of stack trace from previous location ---
    at Java.Interop.JniEnvironment.StaticMethods.CallStaticObjectMethod(JniObjectReference , JniMethodInfo , JniArgumentValue* )
    at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue* )
    at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue[] )
    at Android.Runtime.JNIEnv.FindClass(String )
    at Android.Runtime.JNIEnv.AllocObject(String )
    at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue* )
    at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue[] )
    at Android.Runtime.InputStreamAdapter..ctor(Stream )
    at Android.Runtime.InputStreamAdapter.ToLocalJniHandle(Stream )
    at Android.Webkit.WebResourceResponse..ctor(String , String , Int32 , String , IDictionary`2 , Stream )
    at Microsoft.AspNetCore.Components.WebView.Maui.WebKitWebViewClient.ShouldInterceptRequest(WebView view, IWebResourceRequest request)
    at Android.Webkit.WebViewClient.n_ShouldInterceptRequest_Landroid_webkit_WebView_Landroid_webkit_WebResourceRequest_(IntPtr , IntPtr , IntPtr , IntPtr )
    at crc64d693e2d9159537db.WebKitWebViewClient.n_shouldInterceptRequest(Native Method)
    at crc64d693e2d9159537db.WebKitWebViewClient.shouldInterceptRequest(WebKitWebViewClient.java:39)
    at Rr.a(chromium-TrichromeWebViewGoogle.apk-stable-410410686:16)
    at org.chromium.android_webview.AwContentsBackgroundThreadClient.shouldInterceptRequestFromNative(chromium-TrichromeWebViewGoogle.apk-stable-410410686:2)
    --- End of managed Android.Runtime.JavaProxyThrowable stack trace ---
    android.runtime.JavaProxyThrowable: System.ArgumentException: Arg_DlgtTargMeth
    at System.Delegate.CreateDelegate(Type , Type , String , Boolean , Boolean )
    at System.Delegate.CreateDelegate(Type , Type , String )
    at Android.Runtime.AndroidTypeManager.RegisterNativeMembers(JniType , Type , String )
    --- End of stack trace from previous location ---
    at Java.Interop.JniEnvironment.StaticMethods.CallStaticObjectMethod(JniObjectReference , JniMethodInfo , JniArgumentValue* )
    at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue* )
    at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue[] )
    at Android.Runtime.JNIEnv.FindClass(String )
    at Android.Runtime.JNIEnv.AllocObject(String )
    at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue* )
    at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue[] )
    at Android.Runtime.InputStreamAdapter..ctor(Stream )
    at Android.Runtime.InputStreamAdapter.ToLocalJniHandle(Stream )
    at Android.Webkit.WebResourceResponse..ctor(String , String , Int32 , String , IDictionary`2 , Stream )
    at Microsoft.AspNetCore.Components.WebView.Maui.WebKitWebViewClient.ShouldInterceptRequest(WebView view, IWebResourceRequest request)
    at Android.Webkit.WebViewClient.n_ShouldInterceptRequest_Landroid_webkit_WebView_Landroid_webkit_WebResourceRequest_(IntPtr , IntPtr , IntPtr , IntPtr )
    at crc64d693e2d9159537db.WebKitWebViewClient.n_shouldInterceptRequest(Native Method)
    at crc64d693e2d9159537db.WebKitWebViewClient.shouldInterceptRequest(WebKitWebViewClient.java:39)
    at Rr.a(chromium-TrichromeWebViewGoogle.apk-stable-410410686:16)
    at org.chromium.android_webview.AwContentsBackgroundThreadClient.shouldInterceptRequestFromNative(chromium-TrichromeWebViewGoogle.apk-stable-410410686:2)

It turns out that `Java.IO.InputStream.GetReadHandler()` was linked away.

So we need to preserve:

    <linker>
        <assembly fullname="Mono.Android">
            <type fullname="Android.Runtime.InputStreamAdapter" preserve="methods" />
            <type fullname="Android.Runtime.InputStreamInvoker" preserve="methods" />

Long-term, we should consider reworking `mono.android.jar`, so that
the linker *knows* about any C# methods called from Java from this
library.

This regresses apk size a reasonable amount:

    --"PackageSize": 2680724
    ++"PackageSize": 2697108

Adding ~16kb.

I considered adding:

    <type fullname="Android.Runtime.XmlResourceParserReader" />
    <type fullname="Android.Runtime.XmlPullParserReader" />
    <type fullname="Android.Runtime.XmlReaderResourceParser" />
    <type fullname="Android.Runtime.XmlReaderPullParser" />

But this regressed app size by too much!

    1,141,062 Package size difference 42.57% (of 2,680,724)
jonpryor pushed a commit that referenced this pull request Jan 28, 2022
…asses (#6675)

Fixes: dotnet/maui#2246
Fixes: dotnet/maui#4262
Fixes: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1447865

Context: b7a368a

Revert "[One .NET] Do not preserve IO stream adapter/invoker (#5449)"

This reverts commit 051cad7.

If you run the `maui-blazor` template in a Release build:

	dotnet build -t:Run -c Release

it crashes at runtime:

	Android.Runtime.JavaProxyThrowable: Exception_WasThrown, Android.Runtime.JavaProxyThrowable
	--- End of managed Android.Runtime.JavaProxyThrowable stack trace ---
	android.runtime.JavaProxyThrowable: System.ArgumentException: Arg_DlgtTargMeth
	  at System.Delegate.CreateDelegate(Type , Type , String , Boolean , Boolean )
	  at System.Delegate.CreateDelegate(Type , Type , String )
	  at Android.Runtime.AndroidTypeManager.RegisterNativeMembers(JniType , Type , String )
	--- End of stack trace from previous location ---
	  at Java.Interop.JniEnvironment.StaticMethods.CallStaticObjectMethod(JniObjectReference , JniMethodInfo , JniArgumentValue* )
	  at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue* )
	  at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue[] )
	  at Android.Runtime.JNIEnv.FindClass(String )
	  at Android.Runtime.JNIEnv.AllocObject(String )
	  at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue* )
	  at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue[] )
	  at Android.Runtime.InputStreamAdapter..ctor(Stream )
	  at Android.Runtime.InputStreamAdapter.ToLocalJniHandle(Stream )
	  at Android.Webkit.WebResourceResponse..ctor(String , String , Int32 , String , IDictionary`2 , Stream )
	  at Microsoft.AspNetCore.Components.WebView.Maui.WebKitWebViewClient.ShouldInterceptRequest(WebView view, IWebResourceRequest request)
	  at Android.Webkit.WebViewClient.n_ShouldInterceptRequest_Landroid_webkit_WebView_Landroid_webkit_WebResourceRequest_(IntPtr , IntPtr , IntPtr , IntPtr )
	  at crc64d693e2d9159537db.WebKitWebViewClient.n_shouldInterceptRequest(Native Method)
	  at crc64d693e2d9159537db.WebKitWebViewClient.shouldInterceptRequest(WebKitWebViewClient.java:39)
	  at Rr.a(chromium-TrichromeWebViewGoogle.apk-stable-410410686:16)
	  at org.chromium.android_webview.AwContentsBackgroundThreadClient.shouldInterceptRequestFromNative(chromium-TrichromeWebViewGoogle.apk-stable-410410686:2)
	--- End of managed Android.Runtime.JavaProxyThrowable stack trace ---
	android.runtime.JavaProxyThrowable: System.ArgumentException: Arg_DlgtTargMeth
	  at System.Delegate.CreateDelegate(Type , Type , String , Boolean , Boolean )
	  at System.Delegate.CreateDelegate(Type , Type , String )
	  at Android.Runtime.AndroidTypeManager.RegisterNativeMembers(JniType , Type , String )
	--- End of stack trace from previous location ---
	  at Java.Interop.JniEnvironment.StaticMethods.CallStaticObjectMethod(JniObjectReference , JniMethodInfo , JniArgumentValue* )
	  at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue* )
	  at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue[] )
	  at Android.Runtime.JNIEnv.FindClass(String )
	  at Android.Runtime.JNIEnv.AllocObject(String )
	  at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue* )
	  at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue[] )
	  at Android.Runtime.InputStreamAdapter..ctor(Stream )
	  at Android.Runtime.InputStreamAdapter.ToLocalJniHandle(Stream )
	  at Android.Webkit.WebResourceResponse..ctor(String , String , Int32 , String , IDictionary`2 , Stream )
	  at Microsoft.AspNetCore.Components.WebView.Maui.WebKitWebViewClient.ShouldInterceptRequest(WebView view, IWebResourceRequest request)
	  at Android.Webkit.WebViewClient.n_ShouldInterceptRequest_Landroid_webkit_WebView_Landroid_webkit_WebResourceRequest_(IntPtr , IntPtr , IntPtr , IntPtr )
	  at crc64d693e2d9159537db.WebKitWebViewClient.n_shouldInterceptRequest(Native Method)
	  at crc64d693e2d9159537db.WebKitWebViewClient.shouldInterceptRequest(WebKitWebViewClient.java:39)
	  at Rr.a(chromium-TrichromeWebViewGoogle.apk-stable-410410686:16)
	  at org.chromium.android_webview.AwContentsBackgroundThreadClient.shouldInterceptRequestFromNative(chromium-TrichromeWebViewGoogle.apk-stable-410410686:2)

It turns out that `Java.IO.InputStream.GetReadHandler()` was
linked away.

So we need to preserve:

	<linker>
	    <assembly fullname="Mono.Android">
	        <type fullname="Android.Runtime.InputStreamAdapter" preserve="methods" />
	        <type fullname="Android.Runtime.InputStreamInvoker" preserve="methods" />

Long-term, we should consider reworking `mono.android.jar`, so that
the linker *knows* about any C# methods called from Java from this
library, or *drop* `mono.android.jar` & `mono.android.dex` and treat
`Mono.Android.dll` as a "normal user assembly"…

This regresses `.apk` size by ~16KB:

	--"PackageSize": 2680724
	++"PackageSize": 2697108

I considered adding:

	<type fullname="Android.Runtime.XmlResourceParserReader" />
	<type fullname="Android.Runtime.XmlPullParserReader" />
	<type fullname="Android.Runtime.XmlReaderResourceParser" />
	<type fullname="Android.Runtime.XmlReaderPullParser" />

But this regressed app size by too much!

	1,141,062 Package size difference 42.57% (of 2,680,724)
jonathanpeppers added a commit that referenced this pull request Jan 28, 2022
…asses (#6675)

Fixes: dotnet/maui#2246
Fixes: dotnet/maui#4262
Fixes: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1447865

Context: b7a368a

Revert "[One .NET] Do not preserve IO stream adapter/invoker (#5449)"

This reverts commit 051cad7.

If you run the `maui-blazor` template in a Release build:

	dotnet build -t:Run -c Release

it crashes at runtime:

	Android.Runtime.JavaProxyThrowable: Exception_WasThrown, Android.Runtime.JavaProxyThrowable
	--- End of managed Android.Runtime.JavaProxyThrowable stack trace ---
	android.runtime.JavaProxyThrowable: System.ArgumentException: Arg_DlgtTargMeth
	  at System.Delegate.CreateDelegate(Type , Type , String , Boolean , Boolean )
	  at System.Delegate.CreateDelegate(Type , Type , String )
	  at Android.Runtime.AndroidTypeManager.RegisterNativeMembers(JniType , Type , String )
	--- End of stack trace from previous location ---
	  at Java.Interop.JniEnvironment.StaticMethods.CallStaticObjectMethod(JniObjectReference , JniMethodInfo , JniArgumentValue* )
	  at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue* )
	  at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue[] )
	  at Android.Runtime.JNIEnv.FindClass(String )
	  at Android.Runtime.JNIEnv.AllocObject(String )
	  at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue* )
	  at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue[] )
	  at Android.Runtime.InputStreamAdapter..ctor(Stream )
	  at Android.Runtime.InputStreamAdapter.ToLocalJniHandle(Stream )
	  at Android.Webkit.WebResourceResponse..ctor(String , String , Int32 , String , IDictionary`2 , Stream )
	  at Microsoft.AspNetCore.Components.WebView.Maui.WebKitWebViewClient.ShouldInterceptRequest(WebView view, IWebResourceRequest request)
	  at Android.Webkit.WebViewClient.n_ShouldInterceptRequest_Landroid_webkit_WebView_Landroid_webkit_WebResourceRequest_(IntPtr , IntPtr , IntPtr , IntPtr )
	  at crc64d693e2d9159537db.WebKitWebViewClient.n_shouldInterceptRequest(Native Method)
	  at crc64d693e2d9159537db.WebKitWebViewClient.shouldInterceptRequest(WebKitWebViewClient.java:39)
	  at Rr.a(chromium-TrichromeWebViewGoogle.apk-stable-410410686:16)
	  at org.chromium.android_webview.AwContentsBackgroundThreadClient.shouldInterceptRequestFromNative(chromium-TrichromeWebViewGoogle.apk-stable-410410686:2)
	--- End of managed Android.Runtime.JavaProxyThrowable stack trace ---
	android.runtime.JavaProxyThrowable: System.ArgumentException: Arg_DlgtTargMeth
	  at System.Delegate.CreateDelegate(Type , Type , String , Boolean , Boolean )
	  at System.Delegate.CreateDelegate(Type , Type , String )
	  at Android.Runtime.AndroidTypeManager.RegisterNativeMembers(JniType , Type , String )
	--- End of stack trace from previous location ---
	  at Java.Interop.JniEnvironment.StaticMethods.CallStaticObjectMethod(JniObjectReference , JniMethodInfo , JniArgumentValue* )
	  at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue* )
	  at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue[] )
	  at Android.Runtime.JNIEnv.FindClass(String )
	  at Android.Runtime.JNIEnv.AllocObject(String )
	  at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue* )
	  at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue[] )
	  at Android.Runtime.InputStreamAdapter..ctor(Stream )
	  at Android.Runtime.InputStreamAdapter.ToLocalJniHandle(Stream )
	  at Android.Webkit.WebResourceResponse..ctor(String , String , Int32 , String , IDictionary`2 , Stream )
	  at Microsoft.AspNetCore.Components.WebView.Maui.WebKitWebViewClient.ShouldInterceptRequest(WebView view, IWebResourceRequest request)
	  at Android.Webkit.WebViewClient.n_ShouldInterceptRequest_Landroid_webkit_WebView_Landroid_webkit_WebResourceRequest_(IntPtr , IntPtr , IntPtr , IntPtr )
	  at crc64d693e2d9159537db.WebKitWebViewClient.n_shouldInterceptRequest(Native Method)
	  at crc64d693e2d9159537db.WebKitWebViewClient.shouldInterceptRequest(WebKitWebViewClient.java:39)
	  at Rr.a(chromium-TrichromeWebViewGoogle.apk-stable-410410686:16)
	  at org.chromium.android_webview.AwContentsBackgroundThreadClient.shouldInterceptRequestFromNative(chromium-TrichromeWebViewGoogle.apk-stable-410410686:2)

It turns out that `Java.IO.InputStream.GetReadHandler()` was
linked away.

So we need to preserve:

	<linker>
	    <assembly fullname="Mono.Android">
	        <type fullname="Android.Runtime.InputStreamAdapter" preserve="methods" />
	        <type fullname="Android.Runtime.InputStreamInvoker" preserve="methods" />

Long-term, we should consider reworking `mono.android.jar`, so that
the linker *knows* about any C# methods called from Java from this
library, or *drop* `mono.android.jar` & `mono.android.dex` and treat
`Mono.Android.dll` as a "normal user assembly"…

This regresses `.apk` size by ~16KB:

	--"PackageSize": 2680724
	++"PackageSize": 2697108

I considered adding:

	<type fullname="Android.Runtime.XmlResourceParserReader" />
	<type fullname="Android.Runtime.XmlPullParserReader" />
	<type fullname="Android.Runtime.XmlReaderResourceParser" />
	<type fullname="Android.Runtime.XmlReaderPullParser" />

But this regressed app size by too much!

	1,141,062 Package size difference 42.57% (of 2,680,724)
@github-actions github-actions bot locked and limited conversation to collaborators Jan 26, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants