Skip to content

Commit 5687506

Browse files
[Xamarin.Android.Build.Tasks] enable ForceInterpretedInvoke switch (#7972)
Fixes: dotnet/runtime#83893 Context: dotnet/runtime#72717 In .NET 8, `System.Reflection.{ConstructorInfo,MethodInfo}.Invoke()` will use `System.Reflection.Emit` when called more than once. This impacts startup in mobile applications, so it may not be a desirable feature. Unfortunately, this appears to happen quite easily in Android apps; some examples (using a custom dotnet/runtime build for extra output): * https://gist.github.com/ivanpovazan/2563ea9d2fea320e6425cfcc58da3ee5 * https://gist.github.com/ivanpovazan/d2546d4abad17900d4366cc29e1689b2 The primary situation in which this happens is that all Java-originated `Java.Lang.Object` subclass constructor invocations always hit `ConstructorInfo.Invoke()`; see `TypeManager.Activate()`. To solve this problem, we can set: <ItemGroup> <RuntimeHostConfigurationOption Include="Switch.System.Reflection.ForceInterpretedInvoke" Value="$(_SystemReflectionForceInterpretedInvoke)" Trim="true" /> </ItemGroup> Setting the `Switch.System.Reflection.ForceInterpretedInvoke` switch to True causes the `System.Reflection.Emit` codepath to be *skipped*. We can set `$(_SystemReflectionForceInterpretedInvoke)` to test out the setting in various apps. I added a test to verify the "private" switch is actually set. I also updated the `.aotprofile` to verify that all `System.Reflection.Emit` code paths disappear from `dotnet new android` applications.
1 parent 6352fe0 commit 5687506

File tree

5 files changed

+53
-71
lines changed

5 files changed

+53
-71
lines changed

src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
<_AggressiveAttributeTrimming Condition="'$(_AggressiveAttributeTrimming)' == ''">true</_AggressiveAttributeTrimming>
103103
<NullabilityInfoContextSupport Condition="'$(NullabilityInfoContextSupport)' == ''">false</NullabilityInfoContextSupport>
104104
<BuiltInComInteropSupport Condition="'$(BuiltInComInteropSupport)' == ''">false</BuiltInComInteropSupport>
105+
<_SystemReflectionForceInterpretedInvoke Condition="'$(_SystemReflectionForceInterpretedInvoke)' == ''">true</_SystemReflectionForceInterpretedInvoke>
105106
<!-- Verify DI trimmability at development-time, but turn the validation off for production/trimmed builds. -->
106107
<VerifyDependencyInjectionOpenGenericServiceTrimmability Condition="'$(VerifyDependencyInjectionOpenGenericServiceTrimmability)' == '' and '$(PublishTrimmed)' == 'true'">false</VerifyDependencyInjectionOpenGenericServiceTrimmability>
107108
<VerifyDependencyInjectionOpenGenericServiceTrimmability Condition="'$(VerifyDependencyInjectionOpenGenericServiceTrimmability)' == ''">true</VerifyDependencyInjectionOpenGenericServiceTrimmability>

src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.RuntimeConfig.targets

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ See: https://github.com/dotnet/runtime/blob/b13715b6984889a709ba29ea8a1961db469f
3636
Condition="'$(AndroidUseNegotiateAuthentication)' != ''"
3737
Value="$(AndroidUseNegotiateAuthentication)"
3838
Trim="true" />
39+
<!-- https://github.com/dotnet/runtime/blob/211cdd011f19a51b7092d8365e11e774a8280afb/src/libraries/System.Private.CoreLib/src/System/LocalAppContextSwitches.cs#L52 -->
40+
<RuntimeHostConfigurationOption Include="Switch.System.Reflection.ForceInterpretedInvoke"
41+
Value="$(_SystemReflectionForceInterpretedInvoke)"
42+
Trim="true"
43+
/>
3944
</ItemGroup>
4045

4146
<Target Name="_ParseRuntimeConfigFiles"

src/profiled-aot/dotnet.aotprofile

-3.2 KB
Binary file not shown.

0 commit comments

Comments
 (0)