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

[Mono.Android] handle exceptions in RegisterNativeMembers #6672

Merged

Commits on Jan 26, 2022

  1. [Mono.Android] handle exceptions in RegisterNativeMembers

    Context: dotnet/maui#4262
    
    `dotnet new maui-blazor` crashes at runtime, if you do:
    
        dotnet build -t:Run -c Release
    
    You can turn *off* the linker to solve this issue:
    
        dotnet build -t:Run -c Release -p:AndroidLinkMode=None
    
    (or `PublishTrimmed=false`)
    
    The app crashes in way that you get a native crash:
    
        backtrace:
        #00 pc 000000000065d8fc  /apex/com.android.art/lib64/libart.so (void art::StackVisitor::WalkStack<(art::StackVisitor::CountTransitions)0>(bool)+156) (BuildId: 7fbaf2a1a3317bd634b00eb90e32291e)
        #1 pc 000000000069b25d  /apex/com.android.art/lib64/libart.so (art::Thread::GetCurrentMethod(unsigned int*, bool, bool) const+157) (BuildId: 7fbaf2a1a3317bd634b00eb90e32291e)
        #2 pc 0000000000430fed  /apex/com.android.art/lib64/libart.so (art::JNI<false>::FindClass(_JNIEnv*, char const*)+765) (BuildId: 7fbaf2a1a3317bd634b00eb90e32291e)
        #3 pc 0000000000047e5a  /data/app/~~0Qm6D1S0sO3f1lwfakN0PA==/com.companyname.mauiapp2-08UokVCH5k_PlbZEH_hhkA==/split_config.x86_64.apk!libmono-android.release.so (offset 0x11e000) (java_interop_jnienv_find_class+26) (BuildId: 3d04f8b946590175e97b89aee2e3b19ceed4b524)
        #4 pc 00000000000128ac  <anonymous:41640000>
    
    After much investigation... We found that
    `Java.IO.InputStreamHandler.GetReadHandler()` was linked away.
    
    This is because:
    
    1. `Mono.Android.dll` has it's Java stubs precompiled into
       `mono.android.jar` and `mono.android.dex`.
    
    2. Since `Mono.Android.dll` doesn't go through `GenerateJavaStubs`,
       the linker has no way to know if the missing method is used -- it
       is only called from Java in the crashing app.
    
    To make the crash better, we need to `try-catch` *all* exceptions in
    `RegisterNativeMembers()` and pass them to
    `AndroidRuntime.RaisePendingException()`. This is because
    `RegisterNativeMembers()` is called directly from Java.
    
    Now the crash shows:
    
        01-26 12:20:20.290 29264 29264 I MonoDroid: Android.Runtime.JavaProxyThrowable: Exception_WasThrown, Android.Runtime.JavaProxyThrowable
        01-26 12:20:20.290 29264 29264 I MonoDroid:
        01-26 12:20:20.290 29264 29264 I MonoDroid:   --- End of managed Android.Runtime.JavaProxyThrowable stack trace ---
        01-26 12:20:20.290 29264 29264 I MonoDroid: android.runtime.JavaProxyThrowable: System.ArgumentException: Arg_DlgtTargMeth
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at System.Delegate.CreateDelegate(Type , Type , String , Boolean , Boolean )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at System.Delegate.CreateDelegate(Type , Type , String )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.AndroidTypeManager.RegisterNativeMembers(JniType , Type , String )
        01-26 12:20:20.290 29264 29264 I MonoDroid: --- End of stack trace from previous location ---
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Java.Interop.JniEnvironment.StaticMethods.CallStaticObjectMethod(JniObjectReference , JniMethodInfo , JniArgumentValue* )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue* )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue[] )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.JNIEnv.FindClass(String )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.JNIEnv.AllocObject(String )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue* )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue[] )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.InputStreamAdapter..ctor(Stream )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.InputStreamAdapter.ToLocalJniHandle(Stream )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Webkit.WebResourceResponse..ctor(String , String , Int32 , String , IDictionary`2 , Stream )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Microsoft.AspNetCore.Components.WebView.Maui.WebKitWebViewClient.ShouldInterceptRequest(WebView view, IWebResourceRequest request)
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Webkit.WebViewClient.n_ShouldInterceptRequest_Landroid_webkit_WebView_Landroid_webkit_WebResourceRequest_(IntPtr , IntPtr , IntPtr , IntPtr )
        01-26 12:20:20.290 29264 29264 I MonoDroid: 	at crc64d693e2d9159537db.WebKitWebViewClient.n_shouldInterceptRequest(Native Method)
        01-26 12:20:20.290 29264 29264 I MonoDroid: 	at crc64d693e2d9159537db.WebKitWebViewClient.shouldInterceptRequest(WebKitWebViewClient.java:39)
        01-26 12:20:20.290 29264 29264 I MonoDroid: 	at Rr.a(chromium-TrichromeWebViewGoogle.apk-stable-410410686:16)
        01-26 12:20:20.290 29264 29264 I MonoDroid: 	at org.chromium.android_webview.AwContentsBackgroundThreadClient.shouldInterceptRequestFromNative(chromium-TrichromeWebViewGoogle.apk-stable-410410686:2)
        01-26 12:20:20.290 29264 29264 I MonoDroid:
        01-26 12:20:20.290 29264 29264 I MonoDroid:   --- End of managed Android.Runtime.JavaProxyThrowable stack trace ---
        01-26 12:20:20.290 29264 29264 I MonoDroid: android.runtime.JavaProxyThrowable: System.ArgumentException: Arg_DlgtTargMeth
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at System.Delegate.CreateDelegate(Type , Type , String , Boolean , Boolean )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at System.Delegate.CreateDelegate(Type , Type , String )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.AndroidTypeManager.RegisterNativeMembers(JniType , Type , String )
        01-26 12:20:20.290 29264 29264 I MonoDroid: --- End of stack trace from previous location ---
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Java.Interop.JniEnvironment.StaticMethods.CallStaticObjectMethod(JniObjectReference , JniMethodInfo , JniArgumentValue* )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue* )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue[] )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.JNIEnv.FindClass(String )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.JNIEnv.AllocObject(String )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue* )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue[] )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.InputStreamAdapter..ctor(Stream )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Runtime.InputStreamAdapter.ToLocalJniHandle(Stream )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Webkit.WebResourceResponse..ctor(String , String , Int32 , String , IDictionary`2 , Stream )
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Microsoft.AspNetCore.Components.WebView.Maui.WebKitWebViewClient.ShouldInterceptRequest(WebView view, IWebResourceRequest request)
        01-26 12:20:20.290 29264 29264 I MonoDroid:    at Android.Webkit.WebViewClient.n_ShouldInterceptRequest_Landroid_webkit_WebView_Landroid_webkit_WebResourceRequest_(IntPtr , IntPtr , IntPtr , IntPtr )
        01-26 12:20:20.290 29264 29264 I MonoDroid: 	at crc64d693e2d9159537db.WebKitWebViewClient.n_shouldInterceptRequest(Native Method)
        01-26 12:20:20.290 29264 29264 I MonoDroid: 	at crc64d693e2d9159537db.WebKitWebViewClient.shouldInterceptRequest(WebKitWebViewClient.java:39)
        01-26 12:20:20.290 29264 29264 I MonoDroid: 	at Rr.a(chromium-TrichromeWebViewGoogle.apk-stable-410410686:16)
        01-26 12:20:20.290 29264 29264 I MonoDroid: 	at org.chromium.android_webview.AwContentsBackgroundThreadClient.shouldInterceptRequestFromNative(chromium-TrichromeWebViewGoogle.apk-stable-410410686:2)
    
    This is much easier to reason about, and will save us time in the future.
    
    A fix to the actual linker problem will be coming in another PR.
    jonathanpeppers committed Jan 26, 2022
    Configuration menu
    Copy the full SHA
    1e7fb27 View commit details
    Browse the repository at this point in the history