Skip to content

[TrimmableTypeMap] Reflection-free TrimmableTypeMapType/ValueManager#11801

Draft
simonrozsival wants to merge 32 commits into
mainfrom
dev/simonrozsival/trimmable-managers
Draft

[TrimmableTypeMap] Reflection-free TrimmableTypeMapType/ValueManager#11801
simonrozsival wants to merge 32 commits into
mainfrom
dev/simonrozsival/trimmable-managers

Conversation

@simonrozsival

@simonrozsival simonrozsival commented Jun 29, 2026

Copy link
Copy Markdown
Member

Summary

Adds the reflection-free TrimmableTypeMapValueManager and TrimmableTypeMapTypeManager, plus the opt-in wiring in JNIEnvInit (RuntimeFeature.TrimmableTypeMap) that selects them. Also includes the JavaConvert collection-factory refactor used by the trimmable path. NativeAOT default stays managed; trimmable is opt-in.

Status

All of the earlier prerequisites have now merged into main, and this PR has been rebased on latest main:

With those in main, this PR is no longer stacked or blocked — it contains only the value/type manager implementations on top of them.

@simonrozsival simonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels Jun 29, 2026
@simonrozsival simonrozsival force-pushed the dev/simonrozsival/trimmable-managers branch from 9f999e1 to 4632939 Compare June 30, 2026 10:07
Base automatically changed from dev/simonrozsival/trimmable-typemap-core to main June 30, 2026 12:48
simonrozsival and others added 23 commits June 30, 2026 15:32
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fixes CS0246: 'JavaMarshalValueManager' could not be found. The default
value manager now resolves to the internal CoreClrJavaMarshalValueManager
(accessible via InternalsVisibleTo), matching the pattern in JNIEnvInit.
Suppress the correct trimming warnings (IL2026/IL3050) instead of IL3000.

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

CreatePeerInstance only walked the Java superclass chain, so a Java object
returned through a base-interface signature (e.g. an anonymous class that
implements a derived interface) was marshalled to the base interface's
invoker instead of the most-derived interface proxy.

When targetType is an interface, also enumerate the Java class's interfaces
(recursively into super-interfaces) and select the most-derived registered
.NET type assignable to targetType, mirroring the interface-walk already used
by TrimmableTypeMap.GetProxyForJavaObject.

Fixes JavaInterfaceLookup_BaseInterfaceReturnType_UsesDerivedInterfaceProxy,
TrustManagerFactory_GetTrustManagers_ReturnsIX509TrustManager and the
dependent ServerCertificateCustomValidationCallback_* tests.

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

Extract the Class.getInterfaces() recursive walk into a shared
JavaInterfaceHierarchy.FindFirst helper and use it from both
CoreClrJavaMarshalValueManager.CreatePeerInstance and
TrimmableTypeMap.TryMatchInterfaces, removing the duplicated JNI plumbing
(getInterfaces method id + traversal) from both.

No behavior change; consolidates the interface-derived-proxy resolution
added in the previous commit.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The value-manager/type-manager split reduces the IL3050 AOT-analysis
warnings a basic NativeAOT app produces from 10 to 6: three distinct
warnings (reflection-backed ManagedTypeManager ctor, JNIEnv.MakeArrayType,
JNINativeWrapper.CreateDelegate), each surfaced twice in the MSBuild summary.
Count verified from build.log of the apk and aab NativeAOT runs in CI
build 1485907.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Mono.Android.csproj uses an explicit <Compile> item list, so the new
JavaInterfaceHierarchy.cs was not compiled, causing CS0103 'JavaInterfaceHierarchy
does not exist' in TrimmableTypeMap.cs and CoreClrJavaMarshalValueManager.cs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds TrimmableTypeMapValueManager + reflection-free TrimmableTypeMapTypeManager and
wires opt-in selection (RuntimeFeature.TrimmableTypeMap) in JNIEnvInit. Builds on the
CoreCLR JavaMarshal split. Default stays managed; depends on array-codegen (#11753)
and other slices to be fully functional at runtime.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Revert Color.cs/JavaProxyThrowable.cs formatting, RuntimeFeature feature-gates
(suppressions cover it), and the ITypeMap array-proxy rename (deferred to array PR).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The trimmable typemap path now uses the dedicated TrimmableTypeMapValueManager
(selected in JNIEnvInit.CreateValueManager), so the RuntimeFeature.TrimmableTypeMap
branch in JavaMarshalValueManager.CreatePeer is unreachable. Remove it along with
the now-unused ResolvePeerType/IsIncompatibleCast helpers; that logic lives in
JavaMarshalValueManagerHelper used by the dedicated value manager.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The rebase auto-merge duplicated the JavaArrayProxy attribute class in
JavaPeerProxy.cs (one terse copy from this branch, one documented copy from
core); remove the duplicate. Also align JavaPeerProxy<T>.GetContainerFactory to
use the JavaPeerContainerFactory<T>.Instance singleton (its constructor is
private) instead of 'new'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival simonrozsival force-pushed the dev/simonrozsival/trimmable-managers branch from 74e5d3d to e15e6b9 Compare June 30, 2026 13:34
simonrozsival and others added 2 commits June 30, 2026 15:47
This file was inadvertently reverted to #nullable disable during the rebase
onto main; it carries nullable reference annotations and main (#11799) had it
as #nullable enable. Restore to match.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- TrimmableTypeMapValueManager: remove no-op Dispose(bool) override (sealed
  class) and use ArgumentNullException.ThrowIfNull in ConstructPeerCore.
- TrimmableTypeMapTypeManager: promote GetBuiltInTypeForSimpleReference to a
  class-level method (drops empty XML doc tags) and make GetTypeForSimpleReference
  resolve the first match directly instead of allocating the iterator/enumerator.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
simonrozsival and others added 2 commits June 30, 2026 16:00
Replace the hard-coded (JniObjectReferenceOptions)(1<<1)/(1<<2) literals for
DisposeSource and DoNotRegisterTarget with constant expressions derived from the
public CopyAndDispose / CopyAndDoNotRegister members, so the bits stay pinned to
Java.Interop's public ABI instead of duplicating magic numbers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Concrete types that supply their own Java peer via [JniTypeSignature(GenerateJavaPeer=false)] (DoNotGenerateAcw=true) have no activation ctor or invoker, so ModelBuilder emitted no JavaPeerProxy/TypeMapAssociation for them. At runtime TryGetJniNameForManagedType failed and 'new CrossReferenceBridge()' fell back to the generic mono.android.runtime.JavaObject peer, throwing ArrayStoreException when stored in a typed Java array. This aborted the whole CoreCLRTrimmable/NativeAOT device suites (Zero tests ran).

Emit a minimal proxy + association for concrete self-peer types so the managed→Java JNI name resolves. Adds a regression test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

copilot `copilot-cli` or other AIs were used to author this trimmable-type-map

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant