Skip to content

[TrimmableTypeMap] Implement reflection-free TrimmableTypeMapValueManager and TrimmableTypeMapTypeManager#11617

Open
simonrozsival wants to merge 83 commits into
mainfrom
dev/simonrozsival/java-interop-1441-android
Open

[TrimmableTypeMap] Implement reflection-free TrimmableTypeMapValueManager and TrimmableTypeMapTypeManager#11617
simonrozsival wants to merge 83 commits into
mainfrom
dev/simonrozsival/java-interop-1441-android

Conversation

@simonrozsival

@simonrozsival simonrozsival commented Jun 9, 2026

Copy link
Copy Markdown
Member

Goal

Integrate the Java.Interop value-manager/type-manager split into dotnet/android while keeping the trimmable typemap runtime path reflection-free, AOT-friendly, and covered by targeted tests.

This PR is specifically about making the Android runtime use the new Java.Interop abstractions safely. Broader cleanup such as removing ManagedPeer support or changing NativeAOT runtime policy is intentionally left to follow-up PRs.

Contributes significantly to #10794
Contributes significantly to #11012
Contributes to #8724

What changed

Java.Interop integration

  • Updated the Java.Interop submodule to the follow-up branch for [TrimmableTypeMap] Make adjustments to the base JniValueManager and JniTypeManager to make implementing the trimmable type map easier java-interop#1454.
  • The Java.Interop side now exposes only the minimal object-reference hook needed by JavaObjectArray<T>.SetElementAt():
    • CreateLocalObjectReferenceArgument(Type type, object? value) returns an owned local JniObjectReference for element assignment. Callers must dispose the returned reference.
  • JavaObjectArray<T>.Clear() now directly writes Java null into each slot; it no longer needs value-manager or value-marshaler state.
  • Reflection-backed Java.Interop code still uses value marshalers internally: it creates marshaler state, copies out an independent local reference, then destroys the state immediately.
  • The trimmable Android path does not implement or use GetValueMarshaler*() for JavaObjectArray<T> element assignment.

Runtime manager wiring

  • Switched legacy Mono/CoreCLR Android managers to the Java.Interop ReflectionJniTypeManager / ReflectionJniValueManager base implementations.
  • Added a CoreCLR Android value manager that preserves Android peer registration, GC bridge tracking, activation, and exception unboxing behavior.
  • Added trimmable typemap value/type managers for generated-typemap mode:
    • TrimmableTypeMapTypeManager resolves generated proxy/type-map data without reflection fallback.
    • TrimmableTypeMapValueManager constructs and marshals generated peers without the reflection-backed value manager.
    • Primitive arrays, Java arrays, peerables, proxies, strings, primitive wrappers, and general JavaConvert fallback cases are handled without reflection fallback.
  • Split the large JavaMarshalValueManager.cs implementation into per-type files.
  • Removed the old SimpleValueManager path.

Trimmable typemap build fixes

  • Preserved Microsoft.Android.Runtime.ManagedTypeMapping for linker/type-map steps that still need it.
  • Fixed post-trim Java source/stamp paths for multi-RID CoreCLR builds so RID-specific outputs do not collide or leave stale Java sources behind.
  • Kept [JniAddNativeMethodRegistrationAttribute] diagnostics focused on user assemblies; framework/runtime internal users are handled by generated replacements or intentionally unsupported runtime paths.
  • Removed the unproven RequiresUnreferencedCode annotation from ExportFieldAttribute. [ExportField] is handled by generated trimmable type-map code and does not need to warn simply for constructing the attribute.

Test strategy

  • Trimmable runtime tests exclude TrimmableTypeMapUnsupported via test categories.
  • ManagedPeer-dependent Java.Interop desktop fixture tests remain skipped by category in the trimmable Android lane. This PR does not add Android-local fixture workarounds for those tests; ManagedPeer removal/porting is left to follow-up work.
  • Reflection-manager-only Java.Interop tests remain covered by Java.Interop's standalone test suite; the Android trimmable lane uses generated managers.
  • Added/updated host-side tests for:
    • scanner XA4251 behavior,
    • trimmable runtimeconfig switches,
    • post-trim Java source generation,
    • [Export] / [ExportField] trimmable codegen,
    • trim-warning filtering for generated type-map code.

Review notes / intentional non-goals

  • NativeAOT runtime policy is not broadened in this PR; non-trimmable NativeAOT behavior is left unchanged for a separate PR.
  • ManagedPeer removal is not part of this PR. ManagedPeer-dependent tests are categorized unsupported rather than worked around locally.
  • Java.Interop value marshalers remain implementation detail for reflection-backed Java.Interop behavior; trimmable Android code uses generated managers and direct local object-reference creation.
  • The built-in TypeJniTypeSignature mapping intentionally keeps the current Type.GetTypeCode + explicit nullable typeof checks. Benchmarking showed Nullable.GetUnderlyingType() allocates and should not be used on this path.

Local validation

Validated locally on this branch with:

dotnet build external/Java.Interop/src/Java.Interop/Java.Interop.csproj \
  -p:Configuration=Debug \
  -m:1 \
  -nodeReuse:false \
  --no-restore \
  -v:minimal

dotnet test tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests.csproj \
  -v minimal \
  --no-restore

Results:

  • Java.Interop build passed.
  • Trimmable typemap tests passed (562 passed).
  • dotnet build src/Mono.Android/Mono.Android.csproj -p:Configuration=Debug -p:AndroidSdkDirectory=/Users/simonrozsival/android-toolchain/sdk -m:1 -nodeReuse:false --no-restore -v:minimal compiled Mono.Android.Runtime.dll; the remaining local failure is Android SDK provisioning (extras/android/m2repository.staging and docs.staging missing), not C# or trim-analyzer errors.

Latest update (2026-06-22)

  • Merged latest dotnet/android main into this branch.
  • Updated external/xamarin-android-tools to remove System.IO.Hashing from BaseTasks file hashing helpers. This avoids MSBuild task-host assembly binding failures when local/system SDKs load different System.IO.Hashing / System.Buffers.Binary versions.
  • Changed the trimmable value-manager opaque-object path to use an ACW-generated TrimmableJavaProxyObject instead of falling back to Android.Runtime.JavaObject for arbitrary managed objects.
    • Known primitive/string/array/IJavaObject conversions still use the existing JavaConvert path.
    • Arbitrary opaque managed objects now round-trip through TrimmableJavaProxyObject and unwrap back to the original managed value.
    • The Java peer is generated into mono.android.jar; no duplicate manual java_runtime_trimmable.jar class is added.
    • TrimmableJavaProxyObject derives from Java.Lang.Object so jcw-gen emits Java overrides for equals, hashCode, and toString which call back into the C# proxy implementation.

Additional local validation:

./dotnet-local.sh build --disable-build-servers src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj -c Release --no-restore
./dotnet-local.sh build --disable-build-servers src/java-runtime/java-runtime.csproj -c Release --no-restore
./dotnet-local.sh build --disable-build-servers src/Mono.Android/Mono.Android.csproj -c Release --no-restore
  • Verified mono.android.jar contains net/dot/jni/internal/TrimmableJavaProxyObject.class.
  • Verified java_runtime_trimmable.jar does not contain the trimmable proxy class after cleaning stale intermediates.
  • A trimmable/CoreCLR device run with the ACW proxy reached the test suite; the prior JavaObjectArray<object> failures were gone. Remaining failures were known/unsupported GetValueMarshalerCore cases plus one peer-count assertion (JavaObjectTest.UnregisterFromRuntime) for follow-up triage.
  • Post-merge device install/test retries were blocked by emulator package-manager instability (pm list features / install session broken pipe), not by compilation or duplicate-class errors.

Generate the trimmable typemap once before trimming and reuse the generated Java sources instead of running GenerateTrimmableTypeMap again after ILLink. Keep the linked/R2R typemap assembly packaging path from the previous fix, and remove diagnostics that only supported the deleted post-trim Java copy path.

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

Copy link
Copy Markdown
Member Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@simonrozsival simonrozsival force-pushed the dev/simonrozsival/java-interop-1441-android branch from 42a1b8e to 47450cf Compare June 10, 2026 06:17
@simonrozsival

Copy link
Copy Markdown
Member Author

Rebased onto #11622 (external/Java.Interop d7dbad5) and revalidated targeted Mono.Android build locally.\n\n/azp run

@simonrozsival simonrozsival changed the base branch from main to dependabot/submodules/external/Java.Interop-d7dbad5 June 10, 2026 07:11
@simonrozsival

Copy link
Copy Markdown
Member Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command.

@simonrozsival

Copy link
Copy Markdown
Member Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command.

@simonrozsival

Copy link
Copy Markdown
Member Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command.

@simonrozsival simonrozsival changed the base branch from dependabot/submodules/external/Java.Interop-d7dbad5 to main June 11, 2026 10:15
dependabot Bot and others added 17 commits June 11, 2026 12:15
Bumps [external/Java.Interop](https://github.com/dotnet/java-interop) from `b881d21` to `d7dbad5`.
- [Commits](dotnet/java-interop@b881d21...d7dbad5)

---
updated-dependencies:
- dependency-name: external/Java.Interop
  dependency-version: d7dbad5e30a8f03743a508a95c4e9159fe1f6607
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Split the Android JavaMarshal value manager into CoreCLR and trimmable implementations that share peer registration and GC bridge integration through a reusable helper.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the trimmable typemap value manager on the abstract JniValueManager base, sharing only peer registration and GC bridge state with the CoreCLR value manager. Leave value marshaling unsupported for now until Android has trimmable-specific marshalers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move TrimmableTypeMapTypeManager off ReflectionJniTypeManager and implement type lookup through explicit built-in mappings plus the generated trimmable typemap.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove newly added UnconditionalSuppressMessage attributes, propagate Requires annotations from reflection-backed managers, and carry DAM annotations through JavaPeerProxy/TrimmableTypeMap target type metadata.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace newly added suppressions on reflection-backed managers with RequiresUnreferencedCode and RequiresDynamicCode propagation. Leave trimmable value/type managers free of UnconditionalSuppressMessage attributes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace remaining UnconditionalSuppressMessage attributes in the reflection-backed Android manager implementations with RequiresUnreferencedCode/RequiresDynamicCode where appropriate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace invoker lookup and legacy TypeManager peer creation suppressions with RequiresUnreferencedCode/RequiresDynamicCode propagation. Keep GetObject suppression because adding DAM there breaks delegate/reflection table use sites.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Annotate runtime feature switches with FeatureGuard and structure manager factory branches so reflection-backed manager creation is guarded by the relevant runtime feature instead of broad Requires annotations on the factory methods.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the single-use JavaMarshalReflectionValueManagerBase and keep the shared peer/GC bridge state in JavaMarshalPeerManager, directly delegated by the CoreCLR value manager.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Make both TrimmableTypeMapTypeManager RegisterNativeMembers overloads throw UnreachableException directly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Make unused trimmable JniTypeManager paths fail loudly, remove ManagedPeer from trimmable runtime artifacts, and add an initial AOT-safe value-marshaling implementation for the trimmable value manager.

Update tests and trimmable runtime coverage to use feature switches via AppContext and enable the value-marshaling test bucket for follow-up triage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use the Java.Interop proxy and peerable value marshalers from the trimmable value manager instead of duplicating peerable marshaling locally. This also updates the Java.Interop submodule to the follow-up branch with the shared proxy marshaler and re-enables the trimmable tests now covered by the shared marshalers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
simonrozsival and others added 7 commits June 18, 2026 12:21
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use content-based writes for generated typemap assemblies so generator option changes cannot leave stale DLLs behind. Restore a trim-warning assertion and document the intentional Android-only type mapping behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
simonrozsival and others added 5 commits June 19, 2026 00:55
Resolve built-in reference JNI names when looking up managed array types so CoreCLR trimmable typemap runs can return CLR arrays such as string[] from JniTypeManager.GetTypes(). Keep generated typemap array entries as the first lookup and use dynamic array construction only when CoreCLR supports it.

Also exclude the JavaProxyObject object-method semantics test from trimmable typemap runs pending #11703.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use CoreCLR dynamic type construction at the start of TryGetArrayType when dynamic code is supported, while keeping generated typemap lookup as the NativeAOT path. Keep the helper non-throwing for unsupported array shapes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Make generated trimmable typemap PE assemblies deterministic so unchanged content is not rewritten during incremental builds. Default NativeAOT to trimmable typemaps and reject unsupported NativeAOT typemap implementations early. Adjust NativeAOT publish warning expectations and add focused regression coverage for the target/default behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Include the System.Runtime reference version in the root typemap content fingerprint so the generated module MVID tracks emitted runtime-reference metadata changes. Add regression coverage for this case.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival simonrozsival marked this pull request as ready for review June 22, 2026 10:43
Copilot AI review requested due to automatic review settings June 22, 2026 10:43

Copilot AI 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 integrates Java.Interop’s value-manager/type-manager split into dotnet/android, adding reflection-free managers for the trimmable typemap path and tightening NativeAOT/trimmable typemap wiring across runtime and build tooling.

Changes:

  • Added reflection-free trimmable typemap runtime managers (TrimmableTypeMapTypeManager, TrimmableTypeMapValueManager) and refactored CoreCLR value manager/peer tracking.
  • Updated MSBuild targets/tasks to default NativeAOT to trimmable typemaps, validate configuration, and improve generated Java source handling (including stale file deletion).
  • Updated/expanded tests for scanner diagnostics, typemap build behavior, determinism, and adjusted unsupported test categorization.
Show a summary per file
File Description
tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs Adjust NativeAOT device test skip logic to require trimmable typemaps.
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/TestInstrumentation.cs Exclude new unsupported category under trimmable typemap; remove null-forgiving usage.
tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.cs Update proxy/object-array tests; categorize an unsupported behavior case.
tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Scanner/JavaPeerScannerTests.cs Add targeted test asserting XA4251 reporting for [JniAddNativeMethodRegistration].
src/Xamarin.Android.NamingCustomAttributes/Java.Interop/ExportFieldAttribute.cs Remove trailing whitespace/blank lines.
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets Add validation that NativeAOT requires _AndroidTypeMapImplementation=trimmable.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.MonoVM.apkdesc Update expected packaged sizes/contents for baseline APK.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.NativeAOT.apkdesc Update expected NativeAOT APK size baseline.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.MonoVM.apkdesc Update expected MonoVM APK size baseline.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs Tighten NativeAOT publish to expect no warnings.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs Add NativeAOT default/validation tests; add Java source copy/stale cleanup tests; adjust post-trim assertions.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GenerateTrimmableTypeMapTests.cs Add byte-stability/determinism tests and stale Java deletion coverage.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs Update warning expectations and trimmer-warning test scenarios (incl. NativeAOT).
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs Remove special-case warning allowance for NativeAOT in XA4310 test.
src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs Simplify generation path; always write assemblies/sources; add stale Java deletion output.
src/Xamarin.Android.Build.Tasks/Properties/Resources.resx Remove XA4254/XA4255 resource entries.
src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs Remove XA4254/XA4255 strongly-typed accessors.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets Add typemap output stamp; copy Java sources with incremental semantics; delete stale copied sources.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets Adjust CoreCLR trimmable typemap linker/publish integration after ILLink.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets Default NativeAOT typemap implementation to trimmable.
src/Mono.Android/Mono.Android.csproj Wire in new runtime manager/value-manager source files; remove old ones.
src/Mono.Android/Microsoft.Android.Runtime/TrimmableTypeMapValueManager.PrimitiveArrayHandler.cs Add primitive array wrapper/object-reference handling for trimmable value manager.
src/Mono.Android/Microsoft.Android.Runtime/TrimmableTypeMapValueManager.cs Add reflection-free value manager implementation and peer construction logic for trimmable typemap.
src/Mono.Android/Microsoft.Android.Runtime/TrimmableTypeMapTypeManager.cs Implement reflection-free type manager with built-in signature/type mapping and array handling.
src/Mono.Android/Microsoft.Android.Runtime/TrimmableTypeMap.cs Add DAM-carrying TargetTypeInfo; refine array-type lookup logic and comments.
src/Mono.Android/Microsoft.Android.Runtime/SimpleValueManager.cs Remove old simple value-manager implementation.
src/Mono.Android/Microsoft.Android.Runtime/RuntimeFeature.cs Add FeatureGuards for switches that imply reflection/dynamic code usage.
src/Mono.Android/Microsoft.Android.Runtime/ManagedTypeManager.cs Migrate to JniRuntime.JniTypeManager base; adjust simple-reference mapping flow.
src/Mono.Android/Microsoft.Android.Runtime/JavaMarshalValueManagerHelper.cs Add shared helper for resolving peer target types and cast-compat checks.
src/Mono.Android/Microsoft.Android.Runtime/JavaMarshalRegisteredPeers.cs Extract peer-registration/GC-bridge tracking into reusable component.
src/Mono.Android/Microsoft.Android.Runtime/CoreClrJavaMarshalValueManager.cs Add CoreCLR reflection-backed value manager preserving Android semantics.
src/Mono.Android/Microsoft.Android.Runtime/AndroidReflectionJniValueManager.cs Remove old reflection-backed base value manager.
src/Mono.Android/Java.Interop/TypeManager.cs Add Requires* annotations for legacy peer creation paths.
src/Mono.Android/Java.Interop/JavaPeerProxy.cs Strengthen DAM annotations to carry required members for proxies/invokers.
src/Mono.Android/Java.Interop/JavaObjectExtensions.cs Add Requires* on invoker lookup; simplify reflection calls.
src/Mono.Android/Java.Interop/JavaConvert.cs Add FromObjectReference helper to respect dispose semantics from options.
src/Mono.Android/Android.Runtime/JNINativeWrapper.cs Add RequiresDynamicCode annotation for Reflection.Emit delegate creation.
src/Mono.Android/Android.Runtime/JNIEnvInit.cs Wire new type/value manager selection; enforce NativeAOT → trimmable typemap requirement.
src/Mono.Android/Android.Runtime/JNIEnv.cs Refactor array compatibility checks to avoid problematic array-type creation paths.
src/Mono.Android/Android.Runtime/JavaProxyThrowable.cs Minor whitespace cleanup.
src/Mono.Android/Android.Runtime/AndroidRuntime.cs Ensure JavaProxyThrowable unwrap semantics when mapping throwable → managed exception.
src/Microsoft.Android.Sdk.TrimmableTypeMap/TrimmableTypeMapGenerator.cs Always generate typemap assemblies; remove toggle parameter.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Restrict XA4251 reporting to user assemblies (exclude framework/runtime).
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/RootTypeMapAssemblyGenerator.cs Feed deterministic fingerprint into root typemap assembly preamble.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/PEAssemblyBuilder.cs Add deterministic PE content-id provider.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/MetadataHelper.cs Improve hashing approach and add root fingerprint computation.
src/Microsoft.Android.Sdk.ILLink/PreserveLists/Mono.Android.xml Preserve Microsoft.Android.Runtime.ManagedTypeMapping for linker/type-map steps.
src/Microsoft.Android.Runtime.NativeAOT/Java.Interop/JreRuntime.cs Use Android’s value manager selection for NativeAOT runtime initialization.
Documentation/docs-mobile/messages/xa4254.md Remove documentation for XA4254 (code removed).
Documentation/docs-mobile/messages/xa4255.md Remove documentation for XA4255 (code removed).
Documentation/docs-mobile/messages/index.md Remove XA4254/XA4255 from message index.

Copilot's findings

Files not reviewed (1)
  • src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs: Generated file
  • Files reviewed: 50/51 changed files
  • Comments generated: 2

Comment on lines 120 to 122
Type definition = type.GetGenericTypeDefinition ();
int bt = definition.FullName!.IndexOf ("`", StringComparison.Ordinal);
if (bt == -1)
Comment on lines +212 to +217
throw new ArgumentException (
string.Format (CultureInfo.InvariantCulture, "Requested runtime '{0}' value of '{1}' is not compatible with requested compile-time type T of '{2}'.",
nameof (targetType),
targetType,
typeof (T)),
nameof (targetType));
simonrozsival and others added 6 commits June 22, 2026 12:54
Move incremental SHA256 hashing helpers out of MetadataHelper into a dedicated DeterministicHashBuilder so MetadataHelper only describes the metadata fingerprints it computes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restore DeterministicMvid and EmitPreamble to accept ReadOnlySpan<byte>, and update DeterministicHashBuilder to hash spans without requiring callers to allocate byte arrays.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Revert the broad NativeAOT default and validation change because existing NativeAOT build tests rely on the managed typemap path. Keep the narrower DotNetRun test gating for unsupported NativeAOT typemap combinations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restore the non-trimmable NativeAOT runtime path to use ManagedTypeManager and the Java marshal value manager instead of failing unless TrimmableTypeMap is enabled. Let the managed NativeAOT DotNetRun test combination run again while continuing to skip only the unsupported LLVM-IR typemap combination.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jonathanpeppers pushed a commit to dotnet/java-interop that referenced this pull request Jun 22, 2026
Context from dotnet/android PR dotnet/android#11617: CoreCLR trimmable typemap runs fail tests that depend on unsupported reflection/value-marshaler behavior.

This marks the following tests as `TrimmableTypeMapUnsupported`:

- `JniValueMarshalerContractTests<T>`: these directly test the reflection-based value marshaler APIs. The trimmable typemap runtime intentionally throws if `GetValueMarshalerCore()` is called.
- `JniPeerMembersTests.VirtualInvokeOnBaseInvokesMostDerivedJavaMethod`: this still unexpectedly reaches `GetValueMarshalerCore<T>()` through the test helper constructor path; it should be fixed separately.
- `JavaObjectArray_object_ContractTest`: these inherited collection/list contract tests depend on plain managed `object` values round-tripping through `JavaProxyObject`. The trimmable value manager currently falls back to `JavaConvert.ToLocalJniHandle(value)`, which wraps plain objects as `Android.Runtime.JavaObject` (`mono/android/runtime/JavaObject`) instead of `Java.Interop.JavaProxyObject` (`net/dot/jni/internal/JavaProxyObject`).

Tracking issue for the JavaProxyObject/trimmable typemap support gap: dotnet/android#11703.

Validation:
- `dotnet build external/Java.Interop/tests/Java.Interop-Tests/Java.Interop-Tests.csproj --no-restore --verbosity:minimal`
- Local dotnet/android CoreCLR trimmable device run with `-p:PublishReadyToRun=false`: after these exclusions, the run drops to 2 failures (`TrimmableTypeMapTypeManagerTests.JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics` in dotnet/android and `JniTypeManagerTests.GetType`, which is unrelated to JavaProxyObject object-array contracts).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
simonrozsival and others added 5 commits June 22, 2026 22:09
Update xamarin-android-tools to a commit that avoids span-based System.IO.Hashing APIs in MSBuild task hashing helpers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use an ACW-generated trimmable proxy for arbitrary managed objects so JavaObjectArray<object> round-trips the original managed value instead of an Android.Runtime.JavaObject wrapper.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move the android-tools submodule to a commit that removes System.IO.Hashing from BaseTasks file hashing helpers, avoiding task-host assembly binding failures.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Derive TrimmableJavaProxyObject from Java.Lang.Object so jcw-gen emits ACW overrides for equals, hashCode, and toString that call back into the C# proxy value.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants