dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.14k stars 4.71k forks source link

[Android] System.TypeInitializationException on app startup #108979

Open tipa opened 1 day ago

tipa commented 1 day ago

Description

.NET 8 introduced the AndroidStripILAfterAOT build property. When trying it last year, I encountered this bug, as a consequence I stopped using the option again. It was supposed to be fixed in .NET 9, so I re-enabled it. Now I see crashes in production that I haven't seen before.

Reproduction Steps

I have set these Release-related build properties.

  <PropertyGroup Condition="'$(Configuration)' == 'Release'">
    <AndroidUseDefaultAotProfile>False</AndroidUseDefaultAotProfile>
    <AndroidEnableProfiledAot>True</AndroidEnableProfiledAot>
    <AndroidStripILAfterAOT>True</AndroidStripILAfterAOT>
    <AndroidLinkTool>r8</AndroidLinkTool>
    <TrimMode>full</TrimMode>
    <AndroidAotProfile Include="custom.aprof" />
  </PropertyGroup>

Expected behavior

No crashes

Actual behavior

I get crash reports on Firebase that indicate a System.TypeInitializationException on app launch:

          Fatal Exception: android.runtime.JavaProxyThrowable: [System.TypeInitializationException]: TypeInitialization_Type, MyApp.MyStaticClass
       at MyApp.App.OnCreate + 0x67()
       at Android.App.Application.n_OnCreate + 0x8()
       at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V + 0x5()
       at xyz.App.n_onCreate(App.java)
       at xyz.App.onCreate(App.java:47)
       at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1316)
       at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7848)
       at android.app.ActivityThread.-$$Nest$mhandleBindApplication()
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2486)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loopOnce(Looper.java:230)
       at android.os.Looper.loop(Looper.java:319)
       at android.app.ActivityThread.main(ActivityThread.java:9063)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:588)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)

I also got this exception when the app was launched through a BroadcastReceiver for my widgets:

          Fatal Exception: android.runtime.JavaProxyThrowable: [System.TypeInitializationException]: TypeInitialization_Type, SQLite.SQLiteConnection
       at Unknown.Unknown()
       at MyApp.DatabaseHelper.GetConnection + 0x20()
       at MyApp.DatabaseHelper.get_Db + 0x9()
       at MyApp.MainWidget.BuildRemoteViews + 0x6()
       at MyApp.BaseWidget.OnUpdate + 0xa()
       at Android.Appwidget.AppWidgetProvider.n_OnUpdate_Landroid_content_Context_Landroid_appwidget_AppWidgetManager_arrayI + 0x2a()
       at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLLL_V + 0x5()
       at xyz.BaseWidget.n_onUpdate(BaseWidget.java)
       at xyz.BaseWidget.onUpdate(BaseWidget.java:28)
       at android.appwidget.AppWidgetProvider.onReceive(AppWidgetProvider.java:71)
       at android.app.ActivityThread.handleReceiver(ActivityThread.java:4896)
       at android.app.ActivityThread.-$$Nest$mhandleReceiver()
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2498)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loopOnce(Looper.java:230)
       at android.os.Looper.loop(Looper.java:319)
       at android.app.ActivityThread.main(ActivityThread.java:8919)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:578)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)

Regression?

No response

Known Workarounds

No response

Configuration

android 35.0.0-rc.2.152/9.0.100-rc.2

Other information

I am not sure that this crash is related to AndroidEnableProfiledAot, but since I didn't see those crashes when I use .NET 8 without using that build property, there is reason to assume it.

dotnet-policy-service[bot] commented 1 day ago

Tagging subscribers to 'arch-android': @vitek-karas, @simonrozsival, @steveisok, @akoeplinger See info in area-owners.md if you want to be subscribed.

steveisok commented 1 day ago

@tipa is your custom.aprof generated for net9?

/cc @jonathanpeppers in the off chance this is not something in runtime.

tipa commented 1 day ago

Yes I re-generated the custom.aprof after switching to .NET 9. I haven't regenerated it while using .NET 8 and I didn't have issues doing that (but as I said, I also didn't use AndroidEnableProfiledAot). Could it be necessary to re-generate the custom.aprof after every release now? If that is the case, I would expect the problem to occur for every user, but it's only for a very few (and seemingly not persistent for them), indicating a race condition... (like in the first issue I linked)?

steveisok commented 1 day ago

Could it be necessary to re-generate the custom.aprof after every release now? If that is the case, I would expect the problem to occur for every user, but it's only for a very few (and seemingly not persistent for them), indicating a race condition... (like in the first issue I linked)?

Generally, you'll need to regenerate in order to have a more effective capture. I'm not suggesting it is the problem. Helps capture what your setup is.

jonathanpeppers commented 1 day ago

I would check if the problem still happens without a custom.aprof at all?

I would suspect the issue is enabling $(AndroidStripILAfterAOT) in this app.

tipa commented 1 day ago

Meaning AndroidStripILAfterAOT and custom.aprof are somewhat "incompatible"? I can remove one or the other with my next update (depending on which has the smaller impact on app size) and report back

jonathanpeppers commented 1 day ago

No, I suspect $(AndroidStripILAfterAOT) is the only issue here.