Skip to content

Remove the managed typemap implementation - #12134

Merged
jonathanpeppers merged 6 commits into
mainfrom
android-remove-managed-type-map
Jul 20, 2026
Merged

Remove the managed typemap implementation#12134
jonathanpeppers merged 6 commits into
mainfrom
android-remove-managed-type-map

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented Jul 16, 2026

Copy link
Copy Markdown
Member

Description

Now that NativeAOT defaults to the trimmable typemap (#12121), the reflection-based managed typemap is no longer needed. This PR removes all traces of it. _AndroidTypeMapImplementation now accepts only llvm-ir (Mono/CoreCLR) and trimmable.

Changes

Runtime (src/Mono.Android)

  • Delete ManagedTypeManager and ManagedTypeMapping.
  • Remove the RuntimeFeature.ManagedTypeMap feature switch.
  • Drop the managed branches in JNIEnvInit.CreateTypeManager, JNIEnv.ArrayCreateInstance, and JavaConvert (incl. their IL3050 suppression helpers).

NativeAOT host (src/Microsoft.Android.Runtime.NativeAOT)

  • JreRuntime.CreateDefaultTypeManager now returns TrimmableTypeMapTypeManager unconditionally.

Generator / assembly rewriting

  • Delete the ILLink TypeMappingStep (which rewrote the ManagedTypeMapping method bodies) and its registration in Microsoft.Android.Sdk.TypeMap.LlvmIr.targets.

MSBuild / SDK targets

  • Remove _AndroidUseManagedTypeMap and the ManagedTypeMapRuntimeHostConfigurationOption from RuntimeConfig.targets.
  • Drop managed from the _AndroidTypeMapImplementation validation in Xamarin.Android.Common.targets.
  • Remove the now-dead non-trimmable NativeAOT scaffolding (ILLink-before-ILC path) from Microsoft.Android.Sdk.NativeAOT.targets.

Tests & docs

  • Remove managed test cases (InstallAndRunTests, the obsolete BuildTest2.NativeAOT test).
  • Update .github/copilot-instructions.md and stale comments to list only llvm-ir and trimmable.

Kept intentionally

  • The llvm-ir native typemap path (TypeMapGenerator, GenerateTypeMappings, GenerateEmptyTypemapStub — the managed_to_java_map structures there are the native map's .NET→Java direction, not the managed implementation).
  • XAJavaTypeScanner / XA4212 (a general IJavaObject diagnostic, not managed-specific).
  • The trimmable typemap (SingleUniverseTypeMap, AggregateTypeMap, GenerateMissingTypeMapStubs, etc.).

simonrozsivaland others added 4 commits July 16, 2026 13:33
Now that NativeAOT defaults to the trimmable typemap (#12121), the
reflection-based "managed" typemap is unused. Remove all traces of it:
* Runtime (src/Mono.Android): delete ManagedTypeManager and
ManagedTypeMapping, remove the RuntimeFeature.ManagedTypeMap feature
switch, and drop the managed branches in JNIEnvInit.CreateTypeManager,
JNIEnv.ArrayCreateInstance, and JavaConvert.
* NativeAOT host: JreRuntime.CreateDefaultTypeManager always returns
TrimmableTypeMapTypeManager.
* Generator / assembly rewriting: delete the ILLink TypeMappingStep and
its registration in Microsoft.Android.Sdk.TypeMap.LlvmIr.targets.
* MSBuild/SDK: remove _AndroidUseManagedTypeMap and the ManagedTypeMap
RuntimeHostConfigurationOption, drop "managed" from the
_AndroidTypeMapImplementation validation, and remove the now-dead
non-trimmable NativeAOT scaffolding in
Microsoft.Android.Sdk.NativeAOT.targets.
* Tests/docs: remove "managed" test cases and update documentation to
list only llvm-ir and trimmable.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 40c65ba4-c9e2-442f-bc68-0bd274f0bf8c
The managed marshal methods lookup generated a managed IL table (indexed
by assembly/class/method) so native code could call back into managed to
resolve marshal-method function pointers. It was only ever used by
CoreCLR/NativeAOT; MonoVM always used the native `get_function_pointer`
path, and marshal methods default off for non-MonoVM. Remove the feature
entirely — marshal methods are now MonoVM-only.
* MSBuild codegen: delete ManagedMarshalMethodsLookupInfo and
ManagedMarshalMethodsLookupGenerator; drop the managed-lookup branch in
MarshalMethodsNativeAssemblyGenerator (keep the MonoVM native path), the
index population in MarshalMethodCecilAdapter (+ the AssemblyIndex/
ClassIndex/MethodIndex properties), the rewriter/generator/task plumbing,
and the EnableManagedMarshalMethodsLookup task parameters.
* Native ABI: remove managed_marshal_methods_lookup_enabled from
ApplicationConfig (mono + clr), the DSO stubs, and
managedMarshalMethodsLookupEnabled from JnienvInitializeArgs; drop the
CLR host invariant and the now-dead get_function_pointer_placeholder;
MonoVM always wires up the native get_function_pointer callbacks.
* Runtime: delete ManagedMarshalMethodsLookupTable and the managed
xamarin_app_init p/invoke; remove the struct field + init branch.
* Targets/tests: remove _AndroidUseManagedMarshalMethodsLookup, update
EnvironmentHelper struct mirrors/field counts, and delete the device
test that force-enabled the feature.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 40c65ba4-c9e2-442f-bc68-0bd274f0bf8c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 676a2066-2e01-4963-86bc-942e444a22da
@simonrozsivalsimonrozsival changed the title Remove the "managed" typemap implementationRemove the managed typemap implementationJul 17, 2026
@simonrozsival
simonrozsival marked this pull request as ready for review July 17, 2026 08:15
CopilotAI review requested due to automatic review settings July 17, 2026 08:16

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR removes the reflection-based managed typemap implementation now that NativeAOT defaults to the trimmable typemap, and tightens _AndroidTypeMapImplementation support to only llvm-ir and trimmable. It also deletes the now-dead managed typemap ILLink step and related build/runtime plumbing.

Changes:

  • Removed managed typemap runtime code (ManagedTypeManager/ManagedTypeMapping) and the RuntimeFeature.ManagedTypeMap feature switch.
  • Deleted managed typemap generator/rewriter pieces (ILLink TypeMappingStep, managed marshal-method lookup table/generator, and associated MSBuild properties/targets).
  • Updated targets, tests, and docs to drop managed as a supported/covered configuration.
Show a summary per file
FileDescription
tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.csRemoves managed typemap coverage and deletes a managed marshal-method lookup integration test.
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targetsDrops managed from _AndroidTypeMapImplementation validation; removes managed marshal-method lookup property plumbing; updates generator task parameters.
src/Xamarin.Android.Build.Tasks/Utilities/NativeCodeGenState.csRemoves ManagedMarshalMethodsLookupInfo from build pipeline state.
src/Xamarin.Android.Build.Tasks/Utilities/MarshalMethodsNativeAssemblyGeneratorMonoVM.csUpdates generator constructor signature after managed lookup removal.
src/Xamarin.Android.Build.Tasks/Utilities/MarshalMethodsNativeAssemblyGeneratorCoreCLR.csUpdates generator constructor signature after managed lookup removal.
src/Xamarin.Android.Build.Tasks/Utilities/MarshalMethodsNativeAssemblyGenerator.csRemoves managed marshal-method lookup argument path and always emits token-based get_function_pointer calls.
src/Xamarin.Android.Build.Tasks/Utilities/MarshalMethodsAssemblyRewriter.csRemoves managed lookup generator invocation and corresponding constructor parameter.
src/Xamarin.Android.Build.Tasks/Utilities/MarshalMethodCecilAdapter.csRemoves managed-lookup index propagation into marshal-method entry objects.
src/Xamarin.Android.Build.Tasks/Utilities/ManagedMarshalMethodsLookupInfo.csDeletes managed marshal-method lookup info type.
src/Xamarin.Android.Build.Tasks/Utilities/ManagedMarshalMethodsLookupGenerator.csDeletes managed marshal-method lookup table generator.
src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGeneratorCLR.csRemoves managed marshal-method lookup flag from generated native application_config for CoreCLR.
src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.csRemoves managed marshal-method lookup flag from generated native application_config for MonoVM.
src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigCLR.csRemoves managed marshal-method lookup field from CoreCLR application_config structure definition.
src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfig.csRemoves managed marshal-method lookup field from MonoVM application_config structure definition.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.csUpdates application_config parsing field counts/cases to match native struct changes.
src/Xamarin.Android.Build.Tasks/Tasks/RewriteMarshalMethods.csRemoves managed lookup mode/ordering logic from rewrite pipeline.
src/Xamarin.Android.Build.Tasks/Tasks/GenerateTypeMappings.csUpdates NativeAOT comment to reflect trimmable typemap generation and skips typemap generation for NativeAOT.
src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeMarshalMethodSources.csRemoves managed lookup task property and updates generator construction accordingly.
src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.csRemoves managed marshal-method lookup option and stops emitting it into native config inputs.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.LlvmIr.targetsRemoves managed-lookup task parameter and deletes the ILLink TypeMappingStep registration for managed.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.RuntimeConfig.targetsRemoves _AndroidUseManagedTypeMap and the RuntimeFeature.ManagedTypeMap runtimeconfig option emission.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targetsRemoves non-trimmable NativeAOT scaffolding and makes the trimmable/skip-ILLink path unconditional.
src/native/mono/xamarin-app-stub/xamarin-app.hhRemoves managed marshal-method lookup flag from MonoVM application_config struct.
src/native/mono/xamarin-app-stub/application_dso_stub.ccRemoves managed marshal-method lookup flag initialization in stub config.
src/native/mono/monodroid/xamarin-android-app-context.ccRemoves placeholder get_function_pointer implementation used by the managed lookup path.
src/native/mono/monodroid/monodroid-glue.ccSimplifies marshal-method init: always calls xamarin_app_init with startup/runtime resolver, removing managed lookup branching.
src/native/mono/monodroid/monodroid-glue-internal.hhRemoves placeholder get_function_pointer declaration.
src/native/common/include/managed-interface.hhRemoves managed marshal-method lookup flag from managed initialization args.
src/native/clr/xamarin-app-stub/application_dso_stub.ccRemoves managed marshal-method lookup flag initialization in stub config.
src/native/clr/include/xamarin-app.hhRemoves managed marshal-method lookup flag from CoreCLR application_config struct.
src/native/clr/host/host.ccRemoves passing/validation of managed marshal-method lookup enablement into managed init args.
src/Mono.Android/Mono.Android.csprojStops compiling managed typemap and managed marshal-method lookup table sources.
src/Mono.Android/Microsoft.Android.Runtime/RuntimeFeature.csRemoves RuntimeFeature.ManagedTypeMap feature switch definition.
src/Mono.Android/Microsoft.Android.Runtime/ManagedTypeMapping.csDeletes managed typemap mapping implementation.
src/Mono.Android/Microsoft.Android.Runtime/ManagedTypeManager.csDeletes managed typemap type manager implementation.
src/Mono.Android/Java.Interop/ManagedMarshalMethodsLookupTable.csDeletes managed marshal-method lookup table entrypoint.
src/Mono.Android/Java.Interop/JavaConvert.csRemoves managed typemap branch and its IL3050 suppression helper.
src/Mono.Android/Android.Runtime/JNIEnvInit.csRemoves managed marshal-method lookup init path; removes managed typemap type-manager selection.
src/Mono.Android/Android.Runtime/JNIEnv.csRemoves managed typemap dynamic array-creation fallback and suppression helper.
src/Microsoft.Android.Sdk.ILLink/TypeMappingStep.csDeletes the ILLink custom step that rewrote ManagedTypeMapping bodies.
src/Microsoft.Android.Runtime.NativeAOT/Java.Interop/JreRuntime.csMakes NativeAOT’s default type manager always TrimmableTypeMapTypeManager.
.github/copilot-instructions.mdUpdates docs/examples to list only llvm-ir and trimmable.

Copilot's findings

Comments suppressed due to low confidence (1)

src/Mono.Android/Android.Runtime/JNIEnvInit.cs:151

  • JnienvInitializeArgs still includes marshalMethodsEnabled, but after removing the managedMarshalMethodsLookupEnabled branch there is no longer any CoreCLR initialization path that calls xamarin_app_init to populate the generated get_function_pointer global. Repo-wide search shows xamarin_app_init(...) is only invoked from the MonoVM runtime (src/native/mono/monodroid/monodroid-glue.cc), so CoreCLR apps with marshal methods enabled will likely dereference a null function pointer in the generated marshal method stubs (or never register them correctly).
 JniRuntime.SetCurrent (androidRuntime);
RegisterTrimmableTypeMapNativeMethodsIfNeeded ();
args->propagateUncaughtExceptionFn = (IntPtr)(delegate* unmanaged<IntPtr, IntPtr, IntPtr, void>)&PropagateUncaughtException;
if (!RuntimeFeature.TrimmableTypeMap) {
args->registerJniNativesFn = GetRegisterJniNativesFnPtr ();
}
  • Files reviewed: 42/42 changed files
  • Comments generated: 2

@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot resolve the merge conflicts in this pull request

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Merged origin/main (commits 143d5fb59 and b367d98cd) into this branch. Two conflicts needed manual resolution:

  1. GenerateNativeApplicationConfigSources.cs — kept the new AndroidEnableAssemblyStoreDecompressionCache property from main, dropped EnableManagedMarshalMethodsLookup (removed by this PR).
  2. EnvironmentHelper.cs — resolved ApplicationConfigFieldCount_CoreCLR to 20 (main's 21 minus the removed managed_marshal_methods_lookup_enabled field), and fixed case 20case 19 for assembly_store_decompression_cache_enabled since the preceding managed marshal methods lookup field no longer exists in the struct.

Merge commit: 917a1be85.

@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label Jul 17, 2026
@github-actions

github-actionsBot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Android PR Reviewer completed successfully!

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Code Review — Remove the managed typemap implementation

⚠️Needs Changes (one verification question) — otherwise a clean, well-scoped removal.

Summary

This PR removes the reflection-based managed typemap and the managed marshal-methods lookup table. I verified the removal is complete and internally consistent:

  • No dangling references remain to ManagedTypeMap, ManagedTypeManager, ManagedTypeMapping, ManagedMarshalMethodsLookup*, managed_marshal_methods_lookup_enabled, _AndroidUseManagedTypeMap, TypeMappingStep, or get_function_pointer_placeholder across src/ and tests/.
  • The managed↔native struct pairs stay in sync: the field dropped from JnienvInitializeArgs (C#) matches managed-interface.hh, and managed_marshal_methods_lookup_enabled is removed consistently from ApplicationConfig/ApplicationConfigCLR, both xamarin-app.hh headers, and both application_dso_stub.cc stubs.
  • EnvironmentHelper field counts are correctly decremented (MonoVM 27→26, CoreCLR 21→20) with the trailing case branches removed and remaining cases re-indexed.
  • Deleted files are removed from Mono.Android.csproj; MSBuild validation now correctly accepts only llvm-ir and trimmable.

Findings

  • ⚠️1 question (inline on src/native/clr/host/host.cc): with the managed lookup gone, nothing appears to call xamarin_app_init for the CoreCLR host, so CoreCLR marshal-method function-pointer resolution may be left unwired. Please confirm CoreCLR + marshal-methods Release is covered by device-test CI. This is the only thing I'd want verified before merge.

Positives

  • Excellent cleanup hygiene — dead ILLink step, feature switch, RuntimeHostConfigurationOption, and NativeAOT ILLink-before-ILC scaffolding all removed together.
  • Stale comments in GenerateTypeMappings.cs updated to point at the trimmable type map instead of the deleted TypeMappingStep.
  • Test matrix (InstallAndRunTests) and docs updated to drop the managed cases.

Note: GitHub combined status is currently pending/no checks reported — the Azure DevOps dotnet-android validation should be green (especially device tests) before merge.

Generated by Android PR Reviewer for #12134 · 163.4 AIC · ⌖ 18.9 AIC · ⊞ 6.8K
Comment /review to run again

@@ -431,9 +431,6 @@ void Host::Java_mono_android_Runtime_initInternal (
init.jniAddNativeMethodRegistrationAttributePresent = application_config.jni_add_native_method_registration_attribute_present ? 1 : 0;
init.jniRemappingInUse = application_config.jni_remapping_replacement_type_count > 0 || application_config.jni_remapping_replacement_method_index_entry_count > 0;
init.marshalMethodsEnabled = application_config.marshal_methods_enabled;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 ⚠️JNI interop — Question: how do CoreCLR marshal methods resolve their function pointer now?

Previously, for the CoreCLR host, _AndroidUseManagedMarshalMethodsLookup defaulted to true (the removed Common.targets condition enabled it for any _AndroidRuntime != 'MonoVM'), and the only thing that called xamarin_app_init for CoreCLR was the managed p/invoke in JNIEnvInit.Initialize (xamarin_app_init(args->env, &ManagedMarshalMethodsLookupTable.GetFunctionPointer)) — both removed in this PR.

The generated marshal-method bodies still go through the base MarshalMethodsNativeAssemblyGenerator.WriteBody placeholder path, which loads the get_func_ptr global set by xamarin_app_init. But unlike MonoVM (monodroid-glue.cc calls xamarin_app_init(env, get_function_pointer_at_startup)), the CoreCLR host never calls xamarin_app_init, and there is no get_function_pointer_at_startup implementation under src/native/clr/. With the managed caller gone, that callback appears to stay unset.

Can you confirm a CoreCLR + EnableMarshalMethods=true Release app is covered by device-test CI on this PR? If CoreCLR marshal methods still rely on the managed lookup, removing it here may leave the get_function_pointer callback null at runtime.

(Not blocking review approval — flagging for CI verification.)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marshal methods are not supported with CoreCLR (without the trimmable typemap) because there are issues with the ordering of R2R and post-trimming assembly rewriting (generating marshal methods UCO methods) in outer and inner builds...

@jonathanpeppers
jonathanpeppers merged commit 1b24b11 into mainJul 20, 2026
44 checks passed
@jonathanpeppers
jonathanpeppers deleted the android-remove-managed-type-map branch July 20, 2026 13:43
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

drop-javainterop1ready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers