[TrimmableTypeMap] Use trimmable Java proxy runtime sources - #11271

Merged
simonrozsival merged 8 commits into
mainfrom
trimmable-java-proxy-object
May 11, 2026
Merged

[TrimmableTypeMap] Use trimmable Java proxy runtime sources#11271
simonrozsival merged 8 commits into
mainfrom
trimmable-java-proxy-object

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented May 3, 2026

Copy link
Copy Markdown
Member

Summary

  • add trimmable-specific runtime jars (java_runtime_trimmable_net6.jar and java_runtime_trimmable_clr.jar) that replace Java.Interop's incompatible JavaProxyObject.java / JavaProxyThrowable.java only for _AndroidTypeMapImplementation=trimmable
  • keep the existing non-trimmable runtime jars on Java.Interop's native-registration behavior; _net6 follows the existing historical non-CoreCLR runtime jar naming (java_runtime_net6.jar), not the current .NET TFM
  • include the new trimmable jar/dex outputs in installer file lists and make java-runtime incremental builds account for java-trimmable sources
  • re-enable the affected Java.Interop tests and add focused trimmable JavaProxyObject coverage

Validation

  • dotnet build src/java-runtime/java-runtime.csproj -v:minimal
  • dotnet build src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj -v:minimal
  • dotnet build src/Mono.Android/Mono.Android.csproj -v:minimal
  • MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj -c Debug -p:_AndroidTypeMapImplementation=trimmable -nr:false
  • dotnet test tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests.csproj -v minimal
  • trimmable device instrumentation: 900 passed, 0 failed
  • verified normal runtime jars keep native JavaProxyObject registration, trimmable runtime jars have direct Java object methods and no static native registration

Related issues

@simonrozsival
simonrozsival changed the base branch from main to trimmable-typemap-startup-fixesMay 3, 2026 07:22
@simonrozsival
simonrozsival changed the base branch from trimmable-typemap-startup-fixes to mainMay 3, 2026 07:22
@simonrozsival
simonrozsival changed the base branch from main to trimmable-typemap-startup-fixesMay 3, 2026 07:26
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@github-actions

github-actionsBot commented May 3, 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.

✅ LGTM — Clean, well-structured change

Summary: Introduces trimmable-specific Java runtime jars that replace Java.Interop's JavaProxyObject.java / JavaProxyThrowable.java with versions that don't call ManagedPeer.registerNativeMembers(). This fixes the root cause behind #11170 by providing Java identity implementations of equals/hashCode/toString instead of native methods.

What I verified

  • _AndroidTypeMapImplementation is already in _PropertyCacheItems (line 996), so incremental builds correctly invalidate when switching typemap implementations
  • ✅ The 4-way condition matrix in _CollectRuntimeJarFilenames covers all combinations exhaustively (MonoVM × CoreCLR × default × trimmable)
  • _RuntimeOutput.AddItems metadata is properly added to Inputs for incremental build tracking
  • ✅ The Delete of stale classes.dex prevents D8 output from leaking into jars during incremental builds
  • ✅ New Java files correctly mirror the original Java.Interop implementations minus the static { registerNativeMembers() } block and native method declarations
  • ✅ Installer file lists include all 4 new artifacts (trimmable jar+dex for net6 and clr)
  • ✅ Re-enabled tests (previously excluded due to registerNativeMembers failure) are now validated by 900 passing device tests
  • ✅ New test coverage validates proxy type, object array usage, and Java identity semantics

Positive callouts

  • The RemoveItems/AddItems metadata pattern on _RuntimeOutput is a clean approach to source file swapping — it keeps the build logic centralized in the target without needing separate targets
  • Good test for JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics that explicitly verifies the behavioral contract of the trimmable proxy
  • Removing 27 lines of test exclusions from NUnitInstrumentation.cs is a nice cleanup

CI

The PR is in draft status. The dotnet-android check shows neutral (not yet run). CI results should be verified before merging.

3 💡 suggestions posted inline — all documentation/clarity improvements, no required changes.

Generated by Android PR Reviewer for issue #11271 · ● 6.2M

Comment threadsrc/java-runtime/java-runtime.targets
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 3, 2026
@simonrozsivalsimonrozsival changed the title Use trimmable Java proxy runtime sources[TrimmableTypeMap] Use trimmable Java proxy runtime sourcesMay 3, 2026
Base automatically changed from trimmable-typemap-startup-fixes to mainMay 4, 2026 15:17
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from 1467afa to e66930eCompareMay 4, 2026 18:21
simonrozsivaland others added 2 commits May 4, 2026 20:31
Add trimmable-specific java_runtime jars that replace Java.Interop's JavaProxyObject and JavaProxyThrowable sources only for the trimmable typemap path. Keep the existing runtime jars on Java.Interop's native-registration behavior and select the trimmable jars when _AndroidTypeMapImplementation is trimmable.
Re-enable the affected Java.Interop runtime tests and add focused coverage for JavaProxyObject marshaling/object methods under the trimmable typemap path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add comments documenting runtime jar selection and Java proxy identity semantics.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from e66930e to 0644b70CompareMay 4, 2026 18:31
@simonrozsival
simonrozsival marked this pull request as ready for review May 5, 2026 09:31
CopilotAI review requested due to automatic review settings May 5, 2026 09:31

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 updates the trimmable typemap path to use trimmable-specific Java runtime sources for JavaProxyObject / JavaProxyThrowable, selecting new runtime jars only when _AndroidTypeMapImplementation=trimmable, and re-enables previously excluded Java.Interop tests by adding targeted validation for the new proxy behavior.

Changes:

  • Add trimmable Java runtime proxy sources (src/java-runtime/java-trimmable/...) and build new runtime jar/dex variants for both MonoVM and CoreCLR.
  • Update MSBuild runtime-jar selection logic to choose trimmable vs non-trimmable runtime jars based on _AndroidRuntime × _AndroidTypeMapImplementation.
  • Re-enable previously excluded Java.Interop tests and add focused trimmable coverage around Java proxy marshaling and object-method semantics.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.csRemoves prior trimmable exclusions now that trimmable proxy classes are provided.
tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.csAdds new tests validating marshaling and Java-side JavaProxyObject behavior under trimmable typemap.
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targetsSelects trimmable vs non-trimmable runtime jar based on runtime + typemap implementation.
src/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyThrowable.javaIntroduces trimmable-specific Java proxy throwable implementation.
src/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyObject.javaIntroduces trimmable-specific Java proxy object implementation (no native registration; identity semantics).
src/java-runtime/java-runtime.targetsBuilds additional trimmable runtime jar/dex outputs and improves incremental inputs / stale classes.dex cleanup.
build-tools/installers/create-installers.targetsShips the new trimmable runtime jar/dex artifacts in installers.

Comment threadsrc/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyObject.java Outdated
Use repository Java formatting for trimmable proxy sources and strengthen the proxy hashCode test so it compares against Java identityHashCode instead of itself.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot resolve the merge conflicts in this pull request

CopilotAI commented May 6, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

The merge conflicts are resolved locally:

  • TrimmableTypeMapTypeManagerTests.cs: kept both our JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics test and main's new TryGetArrayType_PrimitiveLeaf_DoesNotRequireRankMapEntry test from [TrimmableTypeMap] Improve array handling #11238.
  • NUnitInstrumentation.cs: kept our HEAD version (the JavaProxyObject/JavaProxyThrowable test exclusions were removed by this PR since the trimmable runtime jar fixes those issues — discarding main's re-addition of them).

However, the push is being rejected by the Xamarin.Android-PR required status check rule (the merge commit's SHA hasn't had CI run against it yet). Could you push the branch manually or trigger CI to unblock? The local merge commit is 4ed4581.

…object
# Conflicts:
#	tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.cs
#	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

MAUI tests are currently broken: #11302

@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 7, 2026
Comment threadsrc/java-runtime/java-runtime.targets Outdated
Comment threadbuild-tools/installers/create-installers.targets Outdated
Drop stale _net6 Java runtime artifact names and collapse the trimmable runtime jar/dex to a single shared artifact for CoreCLR and NativeAOT.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment on lines +42 to +54
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_clr.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_clr.dex" />
</ItemGroup>

<Target Name="_DeleteObsoleteJavaRuntimeArtifacts" BeforeTargets="_BuildJavaRuntimeJar">
<Delete Files="@(_ObsoleteRuntimeOutput)" />
</Target>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We probably don't have to delete these, we could just leave them.

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.

@copilot remove this unnecessary Target and the _ObsoleteRuntimeOutput item.

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.

Done — removed the _ObsoleteRuntimeOutput item group, the _DeleteObsoleteJavaRuntimeArtifacts target, and the leftover @(_ObsoleteRuntimeOutput) reference in _CleanJavaRuntimeJar. The changes are in the local commit but push is blocked by the required CI status check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsival merged commit 22e2966 into mainMay 11, 2026
3 checks passed
@simonrozsival
simonrozsival deleted the trimmable-java-proxy-object branch May 11, 2026 07:16
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 10, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

copilot`copilot-cli` or other AIs were used to author thisready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).trimmable-type-map

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

[TrimmableTypeMap] Use trimmable Java proxy runtime sources - #11271

Merged
simonrozsival merged 8 commits into
mainfrom
trimmable-java-proxy-object
May 11, 2026
Merged

[TrimmableTypeMap] Use trimmable Java proxy runtime sources#11271
simonrozsival merged 8 commits into
mainfrom
trimmable-java-proxy-object

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented May 3, 2026

Copy link
Copy Markdown
Member

Summary

  • add trimmable-specific runtime jars (java_runtime_trimmable_net6.jar and java_runtime_trimmable_clr.jar) that replace Java.Interop's incompatible JavaProxyObject.java / JavaProxyThrowable.java only for _AndroidTypeMapImplementation=trimmable
  • keep the existing non-trimmable runtime jars on Java.Interop's native-registration behavior; _net6 follows the existing historical non-CoreCLR runtime jar naming (java_runtime_net6.jar), not the current .NET TFM
  • include the new trimmable jar/dex outputs in installer file lists and make java-runtime incremental builds account for java-trimmable sources
  • re-enable the affected Java.Interop tests and add focused trimmable JavaProxyObject coverage

Validation

  • dotnet build src/java-runtime/java-runtime.csproj -v:minimal
  • dotnet build src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj -v:minimal
  • dotnet build src/Mono.Android/Mono.Android.csproj -v:minimal
  • MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj -c Debug -p:_AndroidTypeMapImplementation=trimmable -nr:false
  • dotnet test tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests.csproj -v minimal
  • trimmable device instrumentation: 900 passed, 0 failed
  • verified normal runtime jars keep native JavaProxyObject registration, trimmable runtime jars have direct Java object methods and no static native registration

Related issues

@simonrozsival
simonrozsival changed the base branch from main to trimmable-typemap-startup-fixesMay 3, 2026 07:22
@simonrozsival
simonrozsival changed the base branch from trimmable-typemap-startup-fixes to mainMay 3, 2026 07:22
@simonrozsival
simonrozsival changed the base branch from main to trimmable-typemap-startup-fixesMay 3, 2026 07:26
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@github-actions

github-actionsBot commented May 3, 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.

✅ LGTM — Clean, well-structured change

Summary: Introduces trimmable-specific Java runtime jars that replace Java.Interop's JavaProxyObject.java / JavaProxyThrowable.java with versions that don't call ManagedPeer.registerNativeMembers(). This fixes the root cause behind #11170 by providing Java identity implementations of equals/hashCode/toString instead of native methods.

What I verified

  • _AndroidTypeMapImplementation is already in _PropertyCacheItems (line 996), so incremental builds correctly invalidate when switching typemap implementations
  • ✅ The 4-way condition matrix in _CollectRuntimeJarFilenames covers all combinations exhaustively (MonoVM × CoreCLR × default × trimmable)
  • _RuntimeOutput.AddItems metadata is properly added to Inputs for incremental build tracking
  • ✅ The Delete of stale classes.dex prevents D8 output from leaking into jars during incremental builds
  • ✅ New Java files correctly mirror the original Java.Interop implementations minus the static { registerNativeMembers() } block and native method declarations
  • ✅ Installer file lists include all 4 new artifacts (trimmable jar+dex for net6 and clr)
  • ✅ Re-enabled tests (previously excluded due to registerNativeMembers failure) are now validated by 900 passing device tests
  • ✅ New test coverage validates proxy type, object array usage, and Java identity semantics

Positive callouts

  • The RemoveItems/AddItems metadata pattern on _RuntimeOutput is a clean approach to source file swapping — it keeps the build logic centralized in the target without needing separate targets
  • Good test for JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics that explicitly verifies the behavioral contract of the trimmable proxy
  • Removing 27 lines of test exclusions from NUnitInstrumentation.cs is a nice cleanup

CI

The PR is in draft status. The dotnet-android check shows neutral (not yet run). CI results should be verified before merging.

3 💡 suggestions posted inline — all documentation/clarity improvements, no required changes.

Generated by Android PR Reviewer for issue #11271 · ● 6.2M

Comment threadsrc/java-runtime/java-runtime.targets
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 3, 2026
@simonrozsivalsimonrozsival changed the title Use trimmable Java proxy runtime sources[TrimmableTypeMap] Use trimmable Java proxy runtime sourcesMay 3, 2026
Base automatically changed from trimmable-typemap-startup-fixes to mainMay 4, 2026 15:17
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from 1467afa to e66930eCompareMay 4, 2026 18:21
simonrozsivaland others added 2 commits May 4, 2026 20:31
Add trimmable-specific java_runtime jars that replace Java.Interop's JavaProxyObject and JavaProxyThrowable sources only for the trimmable typemap path. Keep the existing runtime jars on Java.Interop's native-registration behavior and select the trimmable jars when _AndroidTypeMapImplementation is trimmable.
Re-enable the affected Java.Interop runtime tests and add focused coverage for JavaProxyObject marshaling/object methods under the trimmable typemap path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add comments documenting runtime jar selection and Java proxy identity semantics.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from e66930e to 0644b70CompareMay 4, 2026 18:31
@simonrozsival
simonrozsival marked this pull request as ready for review May 5, 2026 09:31
CopilotAI review requested due to automatic review settings May 5, 2026 09:31

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 updates the trimmable typemap path to use trimmable-specific Java runtime sources for JavaProxyObject / JavaProxyThrowable, selecting new runtime jars only when _AndroidTypeMapImplementation=trimmable, and re-enables previously excluded Java.Interop tests by adding targeted validation for the new proxy behavior.

Changes:

  • Add trimmable Java runtime proxy sources (src/java-runtime/java-trimmable/...) and build new runtime jar/dex variants for both MonoVM and CoreCLR.
  • Update MSBuild runtime-jar selection logic to choose trimmable vs non-trimmable runtime jars based on _AndroidRuntime × _AndroidTypeMapImplementation.
  • Re-enable previously excluded Java.Interop tests and add focused trimmable coverage around Java proxy marshaling and object-method semantics.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.csRemoves prior trimmable exclusions now that trimmable proxy classes are provided.
tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.csAdds new tests validating marshaling and Java-side JavaProxyObject behavior under trimmable typemap.
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targetsSelects trimmable vs non-trimmable runtime jar based on runtime + typemap implementation.
src/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyThrowable.javaIntroduces trimmable-specific Java proxy throwable implementation.
src/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyObject.javaIntroduces trimmable-specific Java proxy object implementation (no native registration; identity semantics).
src/java-runtime/java-runtime.targetsBuilds additional trimmable runtime jar/dex outputs and improves incremental inputs / stale classes.dex cleanup.
build-tools/installers/create-installers.targetsShips the new trimmable runtime jar/dex artifacts in installers.

Comment threadsrc/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyObject.java Outdated
Use repository Java formatting for trimmable proxy sources and strengthen the proxy hashCode test so it compares against Java identityHashCode instead of itself.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot resolve the merge conflicts in this pull request

CopilotAI commented May 6, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

The merge conflicts are resolved locally:

  • TrimmableTypeMapTypeManagerTests.cs: kept both our JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics test and main's new TryGetArrayType_PrimitiveLeaf_DoesNotRequireRankMapEntry test from [TrimmableTypeMap] Improve array handling #11238.
  • NUnitInstrumentation.cs: kept our HEAD version (the JavaProxyObject/JavaProxyThrowable test exclusions were removed by this PR since the trimmable runtime jar fixes those issues — discarding main's re-addition of them).

However, the push is being rejected by the Xamarin.Android-PR required status check rule (the merge commit's SHA hasn't had CI run against it yet). Could you push the branch manually or trigger CI to unblock? The local merge commit is 4ed4581.

…object
# Conflicts:
#	tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.cs
#	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

MAUI tests are currently broken: #11302

@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 7, 2026
Comment threadsrc/java-runtime/java-runtime.targets Outdated
Comment threadbuild-tools/installers/create-installers.targets Outdated
Drop stale _net6 Java runtime artifact names and collapse the trimmable runtime jar/dex to a single shared artifact for CoreCLR and NativeAOT.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment on lines +42 to +54
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_clr.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_clr.dex" />
</ItemGroup>

<Target Name="_DeleteObsoleteJavaRuntimeArtifacts" BeforeTargets="_BuildJavaRuntimeJar">
<Delete Files="@(_ObsoleteRuntimeOutput)" />
</Target>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We probably don't have to delete these, we could just leave them.

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.

@copilot remove this unnecessary Target and the _ObsoleteRuntimeOutput item.

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.

Done — removed the _ObsoleteRuntimeOutput item group, the _DeleteObsoleteJavaRuntimeArtifacts target, and the leftover @(_ObsoleteRuntimeOutput) reference in _CleanJavaRuntimeJar. The changes are in the local commit but push is blocked by the required CI status check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsival merged commit 22e2966 into mainMay 11, 2026
3 checks passed
@simonrozsival
simonrozsival deleted the trimmable-java-proxy-object branch May 11, 2026 07:16
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 10, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

copilot`copilot-cli` or other AIs were used to author thisready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).trimmable-type-map

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[TrimmableTypeMap] Use trimmable Java proxy runtime sources - #11271

Merged
simonrozsival merged 8 commits into
mainfrom
trimmable-java-proxy-object
May 11, 2026
Merged

[TrimmableTypeMap] Use trimmable Java proxy runtime sources#11271
simonrozsival merged 8 commits into
mainfrom
trimmable-java-proxy-object

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented May 3, 2026

Copy link
Copy Markdown
Member

Summary

  • add trimmable-specific runtime jars (java_runtime_trimmable_net6.jar and java_runtime_trimmable_clr.jar) that replace Java.Interop's incompatible JavaProxyObject.java / JavaProxyThrowable.java only for _AndroidTypeMapImplementation=trimmable
  • keep the existing non-trimmable runtime jars on Java.Interop's native-registration behavior; _net6 follows the existing historical non-CoreCLR runtime jar naming (java_runtime_net6.jar), not the current .NET TFM
  • include the new trimmable jar/dex outputs in installer file lists and make java-runtime incremental builds account for java-trimmable sources
  • re-enable the affected Java.Interop tests and add focused trimmable JavaProxyObject coverage

Validation

  • dotnet build src/java-runtime/java-runtime.csproj -v:minimal
  • dotnet build src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj -v:minimal
  • dotnet build src/Mono.Android/Mono.Android.csproj -v:minimal
  • MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj -c Debug -p:_AndroidTypeMapImplementation=trimmable -nr:false
  • dotnet test tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests.csproj -v minimal
  • trimmable device instrumentation: 900 passed, 0 failed
  • verified normal runtime jars keep native JavaProxyObject registration, trimmable runtime jars have direct Java object methods and no static native registration

Related issues

@simonrozsival
simonrozsival changed the base branch from main to trimmable-typemap-startup-fixesMay 3, 2026 07:22
@simonrozsival
simonrozsival changed the base branch from trimmable-typemap-startup-fixes to mainMay 3, 2026 07:22
@simonrozsival
simonrozsival changed the base branch from main to trimmable-typemap-startup-fixesMay 3, 2026 07:26
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@github-actions

github-actionsBot commented May 3, 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.

✅ LGTM — Clean, well-structured change

Summary: Introduces trimmable-specific Java runtime jars that replace Java.Interop's JavaProxyObject.java / JavaProxyThrowable.java with versions that don't call ManagedPeer.registerNativeMembers(). This fixes the root cause behind #11170 by providing Java identity implementations of equals/hashCode/toString instead of native methods.

What I verified

  • _AndroidTypeMapImplementation is already in _PropertyCacheItems (line 996), so incremental builds correctly invalidate when switching typemap implementations
  • ✅ The 4-way condition matrix in _CollectRuntimeJarFilenames covers all combinations exhaustively (MonoVM × CoreCLR × default × trimmable)
  • _RuntimeOutput.AddItems metadata is properly added to Inputs for incremental build tracking
  • ✅ The Delete of stale classes.dex prevents D8 output from leaking into jars during incremental builds
  • ✅ New Java files correctly mirror the original Java.Interop implementations minus the static { registerNativeMembers() } block and native method declarations
  • ✅ Installer file lists include all 4 new artifacts (trimmable jar+dex for net6 and clr)
  • ✅ Re-enabled tests (previously excluded due to registerNativeMembers failure) are now validated by 900 passing device tests
  • ✅ New test coverage validates proxy type, object array usage, and Java identity semantics

Positive callouts

  • The RemoveItems/AddItems metadata pattern on _RuntimeOutput is a clean approach to source file swapping — it keeps the build logic centralized in the target without needing separate targets
  • Good test for JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics that explicitly verifies the behavioral contract of the trimmable proxy
  • Removing 27 lines of test exclusions from NUnitInstrumentation.cs is a nice cleanup

CI

The PR is in draft status. The dotnet-android check shows neutral (not yet run). CI results should be verified before merging.

3 💡 suggestions posted inline — all documentation/clarity improvements, no required changes.

Generated by Android PR Reviewer for issue #11271 · ● 6.2M

Comment threadsrc/java-runtime/java-runtime.targets
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 3, 2026
@simonrozsivalsimonrozsival changed the title Use trimmable Java proxy runtime sources[TrimmableTypeMap] Use trimmable Java proxy runtime sourcesMay 3, 2026
Base automatically changed from trimmable-typemap-startup-fixes to mainMay 4, 2026 15:17
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from 1467afa to e66930eCompareMay 4, 2026 18:21
simonrozsivaland others added 2 commits May 4, 2026 20:31
Add trimmable-specific java_runtime jars that replace Java.Interop's JavaProxyObject and JavaProxyThrowable sources only for the trimmable typemap path. Keep the existing runtime jars on Java.Interop's native-registration behavior and select the trimmable jars when _AndroidTypeMapImplementation is trimmable.
Re-enable the affected Java.Interop runtime tests and add focused coverage for JavaProxyObject marshaling/object methods under the trimmable typemap path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add comments documenting runtime jar selection and Java proxy identity semantics.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from e66930e to 0644b70CompareMay 4, 2026 18:31
@simonrozsival
simonrozsival marked this pull request as ready for review May 5, 2026 09:31
CopilotAI review requested due to automatic review settings May 5, 2026 09:31

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 updates the trimmable typemap path to use trimmable-specific Java runtime sources for JavaProxyObject / JavaProxyThrowable, selecting new runtime jars only when _AndroidTypeMapImplementation=trimmable, and re-enables previously excluded Java.Interop tests by adding targeted validation for the new proxy behavior.

Changes:

  • Add trimmable Java runtime proxy sources (src/java-runtime/java-trimmable/...) and build new runtime jar/dex variants for both MonoVM and CoreCLR.
  • Update MSBuild runtime-jar selection logic to choose trimmable vs non-trimmable runtime jars based on _AndroidRuntime × _AndroidTypeMapImplementation.
  • Re-enable previously excluded Java.Interop tests and add focused trimmable coverage around Java proxy marshaling and object-method semantics.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.csRemoves prior trimmable exclusions now that trimmable proxy classes are provided.
tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.csAdds new tests validating marshaling and Java-side JavaProxyObject behavior under trimmable typemap.
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targetsSelects trimmable vs non-trimmable runtime jar based on runtime + typemap implementation.
src/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyThrowable.javaIntroduces trimmable-specific Java proxy throwable implementation.
src/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyObject.javaIntroduces trimmable-specific Java proxy object implementation (no native registration; identity semantics).
src/java-runtime/java-runtime.targetsBuilds additional trimmable runtime jar/dex outputs and improves incremental inputs / stale classes.dex cleanup.
build-tools/installers/create-installers.targetsShips the new trimmable runtime jar/dex artifacts in installers.

Comment threadsrc/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyObject.java Outdated
Use repository Java formatting for trimmable proxy sources and strengthen the proxy hashCode test so it compares against Java identityHashCode instead of itself.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot resolve the merge conflicts in this pull request

CopilotAI commented May 6, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

The merge conflicts are resolved locally:

  • TrimmableTypeMapTypeManagerTests.cs: kept both our JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics test and main's new TryGetArrayType_PrimitiveLeaf_DoesNotRequireRankMapEntry test from [TrimmableTypeMap] Improve array handling #11238.
  • NUnitInstrumentation.cs: kept our HEAD version (the JavaProxyObject/JavaProxyThrowable test exclusions were removed by this PR since the trimmable runtime jar fixes those issues — discarding main's re-addition of them).

However, the push is being rejected by the Xamarin.Android-PR required status check rule (the merge commit's SHA hasn't had CI run against it yet). Could you push the branch manually or trigger CI to unblock? The local merge commit is 4ed4581.

…object
# Conflicts:
#	tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.cs
#	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

MAUI tests are currently broken: #11302

@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 7, 2026
Comment threadsrc/java-runtime/java-runtime.targets Outdated
Comment threadbuild-tools/installers/create-installers.targets Outdated
Drop stale _net6 Java runtime artifact names and collapse the trimmable runtime jar/dex to a single shared artifact for CoreCLR and NativeAOT.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment on lines +42 to +54
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_clr.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_clr.dex" />
</ItemGroup>

<Target Name="_DeleteObsoleteJavaRuntimeArtifacts" BeforeTargets="_BuildJavaRuntimeJar">
<Delete Files="@(_ObsoleteRuntimeOutput)" />
</Target>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We probably don't have to delete these, we could just leave them.

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.

@copilot remove this unnecessary Target and the _ObsoleteRuntimeOutput item.

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.

Done — removed the _ObsoleteRuntimeOutput item group, the _DeleteObsoleteJavaRuntimeArtifacts target, and the leftover @(_ObsoleteRuntimeOutput) reference in _CleanJavaRuntimeJar. The changes are in the local commit but push is blocked by the required CI status check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsival merged commit 22e2966 into mainMay 11, 2026
3 checks passed
@simonrozsival
simonrozsival deleted the trimmable-java-proxy-object branch May 11, 2026 07:16
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 10, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

copilot`copilot-cli` or other AIs were used to author thisready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).trimmable-type-map

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[TrimmableTypeMap] Use trimmable Java proxy runtime sources - #11271

Merged
simonrozsival merged 8 commits into
mainfrom
trimmable-java-proxy-object
May 11, 2026
Merged

[TrimmableTypeMap] Use trimmable Java proxy runtime sources#11271
simonrozsival merged 8 commits into
mainfrom
trimmable-java-proxy-object

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented May 3, 2026

Copy link
Copy Markdown
Member

Summary

  • add trimmable-specific runtime jars (java_runtime_trimmable_net6.jar and java_runtime_trimmable_clr.jar) that replace Java.Interop's incompatible JavaProxyObject.java / JavaProxyThrowable.java only for _AndroidTypeMapImplementation=trimmable
  • keep the existing non-trimmable runtime jars on Java.Interop's native-registration behavior; _net6 follows the existing historical non-CoreCLR runtime jar naming (java_runtime_net6.jar), not the current .NET TFM
  • include the new trimmable jar/dex outputs in installer file lists and make java-runtime incremental builds account for java-trimmable sources
  • re-enable the affected Java.Interop tests and add focused trimmable JavaProxyObject coverage

Validation

  • dotnet build src/java-runtime/java-runtime.csproj -v:minimal
  • dotnet build src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj -v:minimal
  • dotnet build src/Mono.Android/Mono.Android.csproj -v:minimal
  • MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj -c Debug -p:_AndroidTypeMapImplementation=trimmable -nr:false
  • dotnet test tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests.csproj -v minimal
  • trimmable device instrumentation: 900 passed, 0 failed
  • verified normal runtime jars keep native JavaProxyObject registration, trimmable runtime jars have direct Java object methods and no static native registration

Related issues

@simonrozsival
simonrozsival changed the base branch from main to trimmable-typemap-startup-fixesMay 3, 2026 07:22
@simonrozsival
simonrozsival changed the base branch from trimmable-typemap-startup-fixes to mainMay 3, 2026 07:22
@simonrozsival
simonrozsival changed the base branch from main to trimmable-typemap-startup-fixesMay 3, 2026 07:26
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@github-actions

github-actionsBot commented May 3, 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.

✅ LGTM — Clean, well-structured change

Summary: Introduces trimmable-specific Java runtime jars that replace Java.Interop's JavaProxyObject.java / JavaProxyThrowable.java with versions that don't call ManagedPeer.registerNativeMembers(). This fixes the root cause behind #11170 by providing Java identity implementations of equals/hashCode/toString instead of native methods.

What I verified

  • _AndroidTypeMapImplementation is already in _PropertyCacheItems (line 996), so incremental builds correctly invalidate when switching typemap implementations
  • ✅ The 4-way condition matrix in _CollectRuntimeJarFilenames covers all combinations exhaustively (MonoVM × CoreCLR × default × trimmable)
  • _RuntimeOutput.AddItems metadata is properly added to Inputs for incremental build tracking
  • ✅ The Delete of stale classes.dex prevents D8 output from leaking into jars during incremental builds
  • ✅ New Java files correctly mirror the original Java.Interop implementations minus the static { registerNativeMembers() } block and native method declarations
  • ✅ Installer file lists include all 4 new artifacts (trimmable jar+dex for net6 and clr)
  • ✅ Re-enabled tests (previously excluded due to registerNativeMembers failure) are now validated by 900 passing device tests
  • ✅ New test coverage validates proxy type, object array usage, and Java identity semantics

Positive callouts

  • The RemoveItems/AddItems metadata pattern on _RuntimeOutput is a clean approach to source file swapping — it keeps the build logic centralized in the target without needing separate targets
  • Good test for JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics that explicitly verifies the behavioral contract of the trimmable proxy
  • Removing 27 lines of test exclusions from NUnitInstrumentation.cs is a nice cleanup

CI

The PR is in draft status. The dotnet-android check shows neutral (not yet run). CI results should be verified before merging.

3 💡 suggestions posted inline — all documentation/clarity improvements, no required changes.

Generated by Android PR Reviewer for issue #11271 · ● 6.2M

Comment threadsrc/java-runtime/java-runtime.targets
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 3, 2026
@simonrozsivalsimonrozsival changed the title Use trimmable Java proxy runtime sources[TrimmableTypeMap] Use trimmable Java proxy runtime sourcesMay 3, 2026
Base automatically changed from trimmable-typemap-startup-fixes to mainMay 4, 2026 15:17
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from 1467afa to e66930eCompareMay 4, 2026 18:21
simonrozsivaland others added 2 commits May 4, 2026 20:31
Add trimmable-specific java_runtime jars that replace Java.Interop's JavaProxyObject and JavaProxyThrowable sources only for the trimmable typemap path. Keep the existing runtime jars on Java.Interop's native-registration behavior and select the trimmable jars when _AndroidTypeMapImplementation is trimmable.
Re-enable the affected Java.Interop runtime tests and add focused coverage for JavaProxyObject marshaling/object methods under the trimmable typemap path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add comments documenting runtime jar selection and Java proxy identity semantics.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from e66930e to 0644b70CompareMay 4, 2026 18:31
@simonrozsival
simonrozsival marked this pull request as ready for review May 5, 2026 09:31
CopilotAI review requested due to automatic review settings May 5, 2026 09:31

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 updates the trimmable typemap path to use trimmable-specific Java runtime sources for JavaProxyObject / JavaProxyThrowable, selecting new runtime jars only when _AndroidTypeMapImplementation=trimmable, and re-enables previously excluded Java.Interop tests by adding targeted validation for the new proxy behavior.

Changes:

  • Add trimmable Java runtime proxy sources (src/java-runtime/java-trimmable/...) and build new runtime jar/dex variants for both MonoVM and CoreCLR.
  • Update MSBuild runtime-jar selection logic to choose trimmable vs non-trimmable runtime jars based on _AndroidRuntime × _AndroidTypeMapImplementation.
  • Re-enable previously excluded Java.Interop tests and add focused trimmable coverage around Java proxy marshaling and object-method semantics.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.csRemoves prior trimmable exclusions now that trimmable proxy classes are provided.
tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.csAdds new tests validating marshaling and Java-side JavaProxyObject behavior under trimmable typemap.
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targetsSelects trimmable vs non-trimmable runtime jar based on runtime + typemap implementation.
src/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyThrowable.javaIntroduces trimmable-specific Java proxy throwable implementation.
src/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyObject.javaIntroduces trimmable-specific Java proxy object implementation (no native registration; identity semantics).
src/java-runtime/java-runtime.targetsBuilds additional trimmable runtime jar/dex outputs and improves incremental inputs / stale classes.dex cleanup.
build-tools/installers/create-installers.targetsShips the new trimmable runtime jar/dex artifacts in installers.

Comment threadsrc/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyObject.java Outdated
Use repository Java formatting for trimmable proxy sources and strengthen the proxy hashCode test so it compares against Java identityHashCode instead of itself.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot resolve the merge conflicts in this pull request

CopilotAI commented May 6, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

The merge conflicts are resolved locally:

  • TrimmableTypeMapTypeManagerTests.cs: kept both our JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics test and main's new TryGetArrayType_PrimitiveLeaf_DoesNotRequireRankMapEntry test from [TrimmableTypeMap] Improve array handling #11238.
  • NUnitInstrumentation.cs: kept our HEAD version (the JavaProxyObject/JavaProxyThrowable test exclusions were removed by this PR since the trimmable runtime jar fixes those issues — discarding main's re-addition of them).

However, the push is being rejected by the Xamarin.Android-PR required status check rule (the merge commit's SHA hasn't had CI run against it yet). Could you push the branch manually or trigger CI to unblock? The local merge commit is 4ed4581.

…object
# Conflicts:
#	tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.cs
#	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

MAUI tests are currently broken: #11302

@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 7, 2026
Comment threadsrc/java-runtime/java-runtime.targets Outdated
Comment threadbuild-tools/installers/create-installers.targets Outdated
Drop stale _net6 Java runtime artifact names and collapse the trimmable runtime jar/dex to a single shared artifact for CoreCLR and NativeAOT.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment on lines +42 to +54
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_clr.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_clr.dex" />
</ItemGroup>

<Target Name="_DeleteObsoleteJavaRuntimeArtifacts" BeforeTargets="_BuildJavaRuntimeJar">
<Delete Files="@(_ObsoleteRuntimeOutput)" />
</Target>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We probably don't have to delete these, we could just leave them.

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.

@copilot remove this unnecessary Target and the _ObsoleteRuntimeOutput item.

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.

Done — removed the _ObsoleteRuntimeOutput item group, the _DeleteObsoleteJavaRuntimeArtifacts target, and the leftover @(_ObsoleteRuntimeOutput) reference in _CleanJavaRuntimeJar. The changes are in the local commit but push is blocked by the required CI status check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsival merged commit 22e2966 into mainMay 11, 2026
3 checks passed
@simonrozsival
simonrozsival deleted the trimmable-java-proxy-object branch May 11, 2026 07:16
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 10, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

copilot`copilot-cli` or other AIs were used to author thisready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).trimmable-type-map

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

[TrimmableTypeMap] Use trimmable Java proxy runtime sources - #11271

Merged
simonrozsival merged 8 commits into
mainfrom
trimmable-java-proxy-object
May 11, 2026
Merged

[TrimmableTypeMap] Use trimmable Java proxy runtime sources#11271
simonrozsival merged 8 commits into
mainfrom
trimmable-java-proxy-object

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented May 3, 2026

Copy link
Copy Markdown
Member

Summary

  • add trimmable-specific runtime jars (java_runtime_trimmable_net6.jar and java_runtime_trimmable_clr.jar) that replace Java.Interop's incompatible JavaProxyObject.java / JavaProxyThrowable.java only for _AndroidTypeMapImplementation=trimmable
  • keep the existing non-trimmable runtime jars on Java.Interop's native-registration behavior; _net6 follows the existing historical non-CoreCLR runtime jar naming (java_runtime_net6.jar), not the current .NET TFM
  • include the new trimmable jar/dex outputs in installer file lists and make java-runtime incremental builds account for java-trimmable sources
  • re-enable the affected Java.Interop tests and add focused trimmable JavaProxyObject coverage

Validation

  • dotnet build src/java-runtime/java-runtime.csproj -v:minimal
  • dotnet build src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj -v:minimal
  • dotnet build src/Mono.Android/Mono.Android.csproj -v:minimal
  • MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj -c Debug -p:_AndroidTypeMapImplementation=trimmable -nr:false
  • dotnet test tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests.csproj -v minimal
  • trimmable device instrumentation: 900 passed, 0 failed
  • verified normal runtime jars keep native JavaProxyObject registration, trimmable runtime jars have direct Java object methods and no static native registration

Related issues

@simonrozsival
simonrozsival changed the base branch from main to trimmable-typemap-startup-fixesMay 3, 2026 07:22
@simonrozsival
simonrozsival changed the base branch from trimmable-typemap-startup-fixes to mainMay 3, 2026 07:22
@simonrozsival
simonrozsival changed the base branch from main to trimmable-typemap-startup-fixesMay 3, 2026 07:26
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@github-actions

github-actionsBot commented May 3, 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.

✅ LGTM — Clean, well-structured change

Summary: Introduces trimmable-specific Java runtime jars that replace Java.Interop's JavaProxyObject.java / JavaProxyThrowable.java with versions that don't call ManagedPeer.registerNativeMembers(). This fixes the root cause behind #11170 by providing Java identity implementations of equals/hashCode/toString instead of native methods.

What I verified

  • _AndroidTypeMapImplementation is already in _PropertyCacheItems (line 996), so incremental builds correctly invalidate when switching typemap implementations
  • ✅ The 4-way condition matrix in _CollectRuntimeJarFilenames covers all combinations exhaustively (MonoVM × CoreCLR × default × trimmable)
  • _RuntimeOutput.AddItems metadata is properly added to Inputs for incremental build tracking
  • ✅ The Delete of stale classes.dex prevents D8 output from leaking into jars during incremental builds
  • ✅ New Java files correctly mirror the original Java.Interop implementations minus the static { registerNativeMembers() } block and native method declarations
  • ✅ Installer file lists include all 4 new artifacts (trimmable jar+dex for net6 and clr)
  • ✅ Re-enabled tests (previously excluded due to registerNativeMembers failure) are now validated by 900 passing device tests
  • ✅ New test coverage validates proxy type, object array usage, and Java identity semantics

Positive callouts

  • The RemoveItems/AddItems metadata pattern on _RuntimeOutput is a clean approach to source file swapping — it keeps the build logic centralized in the target without needing separate targets
  • Good test for JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics that explicitly verifies the behavioral contract of the trimmable proxy
  • Removing 27 lines of test exclusions from NUnitInstrumentation.cs is a nice cleanup

CI

The PR is in draft status. The dotnet-android check shows neutral (not yet run). CI results should be verified before merging.

3 💡 suggestions posted inline — all documentation/clarity improvements, no required changes.

Generated by Android PR Reviewer for issue #11271 · ● 6.2M

Comment threadsrc/java-runtime/java-runtime.targets
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 3, 2026
@simonrozsivalsimonrozsival changed the title Use trimmable Java proxy runtime sources[TrimmableTypeMap] Use trimmable Java proxy runtime sourcesMay 3, 2026
Base automatically changed from trimmable-typemap-startup-fixes to mainMay 4, 2026 15:17
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from 1467afa to e66930eCompareMay 4, 2026 18:21
simonrozsivaland others added 2 commits May 4, 2026 20:31
Add trimmable-specific java_runtime jars that replace Java.Interop's JavaProxyObject and JavaProxyThrowable sources only for the trimmable typemap path. Keep the existing runtime jars on Java.Interop's native-registration behavior and select the trimmable jars when _AndroidTypeMapImplementation is trimmable.
Re-enable the affected Java.Interop runtime tests and add focused coverage for JavaProxyObject marshaling/object methods under the trimmable typemap path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add comments documenting runtime jar selection and Java proxy identity semantics.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from e66930e to 0644b70CompareMay 4, 2026 18:31
@simonrozsival
simonrozsival marked this pull request as ready for review May 5, 2026 09:31
CopilotAI review requested due to automatic review settings May 5, 2026 09:31

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 updates the trimmable typemap path to use trimmable-specific Java runtime sources for JavaProxyObject / JavaProxyThrowable, selecting new runtime jars only when _AndroidTypeMapImplementation=trimmable, and re-enables previously excluded Java.Interop tests by adding targeted validation for the new proxy behavior.

Changes:

  • Add trimmable Java runtime proxy sources (src/java-runtime/java-trimmable/...) and build new runtime jar/dex variants for both MonoVM and CoreCLR.
  • Update MSBuild runtime-jar selection logic to choose trimmable vs non-trimmable runtime jars based on _AndroidRuntime × _AndroidTypeMapImplementation.
  • Re-enable previously excluded Java.Interop tests and add focused trimmable coverage around Java proxy marshaling and object-method semantics.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.csRemoves prior trimmable exclusions now that trimmable proxy classes are provided.
tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.csAdds new tests validating marshaling and Java-side JavaProxyObject behavior under trimmable typemap.
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targetsSelects trimmable vs non-trimmable runtime jar based on runtime + typemap implementation.
src/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyThrowable.javaIntroduces trimmable-specific Java proxy throwable implementation.
src/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyObject.javaIntroduces trimmable-specific Java proxy object implementation (no native registration; identity semantics).
src/java-runtime/java-runtime.targetsBuilds additional trimmable runtime jar/dex outputs and improves incremental inputs / stale classes.dex cleanup.
build-tools/installers/create-installers.targetsShips the new trimmable runtime jar/dex artifacts in installers.

Comment threadsrc/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyObject.java Outdated
Use repository Java formatting for trimmable proxy sources and strengthen the proxy hashCode test so it compares against Java identityHashCode instead of itself.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot resolve the merge conflicts in this pull request

CopilotAI commented May 6, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

The merge conflicts are resolved locally:

  • TrimmableTypeMapTypeManagerTests.cs: kept both our JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics test and main's new TryGetArrayType_PrimitiveLeaf_DoesNotRequireRankMapEntry test from [TrimmableTypeMap] Improve array handling #11238.
  • NUnitInstrumentation.cs: kept our HEAD version (the JavaProxyObject/JavaProxyThrowable test exclusions were removed by this PR since the trimmable runtime jar fixes those issues — discarding main's re-addition of them).

However, the push is being rejected by the Xamarin.Android-PR required status check rule (the merge commit's SHA hasn't had CI run against it yet). Could you push the branch manually or trigger CI to unblock? The local merge commit is 4ed4581.

…object
# Conflicts:
#	tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.cs
#	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

MAUI tests are currently broken: #11302

@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 7, 2026
Comment threadsrc/java-runtime/java-runtime.targets Outdated
Comment threadbuild-tools/installers/create-installers.targets Outdated
Drop stale _net6 Java runtime artifact names and collapse the trimmable runtime jar/dex to a single shared artifact for CoreCLR and NativeAOT.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment on lines +42 to +54
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_clr.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_clr.dex" />
</ItemGroup>

<Target Name="_DeleteObsoleteJavaRuntimeArtifacts" BeforeTargets="_BuildJavaRuntimeJar">
<Delete Files="@(_ObsoleteRuntimeOutput)" />
</Target>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We probably don't have to delete these, we could just leave them.

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.

@copilot remove this unnecessary Target and the _ObsoleteRuntimeOutput item.

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.

Done — removed the _ObsoleteRuntimeOutput item group, the _DeleteObsoleteJavaRuntimeArtifacts target, and the leftover @(_ObsoleteRuntimeOutput) reference in _CleanJavaRuntimeJar. The changes are in the local commit but push is blocked by the required CI status check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsival merged commit 22e2966 into mainMay 11, 2026
3 checks passed
@simonrozsival
simonrozsival deleted the trimmable-java-proxy-object branch May 11, 2026 07:16
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 10, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

copilot`copilot-cli` or other AIs were used to author thisready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).trimmable-type-map

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[TrimmableTypeMap] Use trimmable Java proxy runtime sources - #11271

Merged
simonrozsival merged 8 commits into
mainfrom
trimmable-java-proxy-object
May 11, 2026
Merged

[TrimmableTypeMap] Use trimmable Java proxy runtime sources#11271
simonrozsival merged 8 commits into
mainfrom
trimmable-java-proxy-object

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented May 3, 2026

Copy link
Copy Markdown
Member

Summary

  • add trimmable-specific runtime jars (java_runtime_trimmable_net6.jar and java_runtime_trimmable_clr.jar) that replace Java.Interop's incompatible JavaProxyObject.java / JavaProxyThrowable.java only for _AndroidTypeMapImplementation=trimmable
  • keep the existing non-trimmable runtime jars on Java.Interop's native-registration behavior; _net6 follows the existing historical non-CoreCLR runtime jar naming (java_runtime_net6.jar), not the current .NET TFM
  • include the new trimmable jar/dex outputs in installer file lists and make java-runtime incremental builds account for java-trimmable sources
  • re-enable the affected Java.Interop tests and add focused trimmable JavaProxyObject coverage

Validation

  • dotnet build src/java-runtime/java-runtime.csproj -v:minimal
  • dotnet build src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj -v:minimal
  • dotnet build src/Mono.Android/Mono.Android.csproj -v:minimal
  • MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj -c Debug -p:_AndroidTypeMapImplementation=trimmable -nr:false
  • dotnet test tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests.csproj -v minimal
  • trimmable device instrumentation: 900 passed, 0 failed
  • verified normal runtime jars keep native JavaProxyObject registration, trimmable runtime jars have direct Java object methods and no static native registration

Related issues

@simonrozsival
simonrozsival changed the base branch from main to trimmable-typemap-startup-fixesMay 3, 2026 07:22
@simonrozsival
simonrozsival changed the base branch from trimmable-typemap-startup-fixes to mainMay 3, 2026 07:22
@simonrozsival
simonrozsival changed the base branch from main to trimmable-typemap-startup-fixesMay 3, 2026 07:26
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@github-actions

github-actionsBot commented May 3, 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.

✅ LGTM — Clean, well-structured change

Summary: Introduces trimmable-specific Java runtime jars that replace Java.Interop's JavaProxyObject.java / JavaProxyThrowable.java with versions that don't call ManagedPeer.registerNativeMembers(). This fixes the root cause behind #11170 by providing Java identity implementations of equals/hashCode/toString instead of native methods.

What I verified

  • _AndroidTypeMapImplementation is already in _PropertyCacheItems (line 996), so incremental builds correctly invalidate when switching typemap implementations
  • ✅ The 4-way condition matrix in _CollectRuntimeJarFilenames covers all combinations exhaustively (MonoVM × CoreCLR × default × trimmable)
  • _RuntimeOutput.AddItems metadata is properly added to Inputs for incremental build tracking
  • ✅ The Delete of stale classes.dex prevents D8 output from leaking into jars during incremental builds
  • ✅ New Java files correctly mirror the original Java.Interop implementations minus the static { registerNativeMembers() } block and native method declarations
  • ✅ Installer file lists include all 4 new artifacts (trimmable jar+dex for net6 and clr)
  • ✅ Re-enabled tests (previously excluded due to registerNativeMembers failure) are now validated by 900 passing device tests
  • ✅ New test coverage validates proxy type, object array usage, and Java identity semantics

Positive callouts

  • The RemoveItems/AddItems metadata pattern on _RuntimeOutput is a clean approach to source file swapping — it keeps the build logic centralized in the target without needing separate targets
  • Good test for JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics that explicitly verifies the behavioral contract of the trimmable proxy
  • Removing 27 lines of test exclusions from NUnitInstrumentation.cs is a nice cleanup

CI

The PR is in draft status. The dotnet-android check shows neutral (not yet run). CI results should be verified before merging.

3 💡 suggestions posted inline — all documentation/clarity improvements, no required changes.

Generated by Android PR Reviewer for issue #11271 · ● 6.2M

Comment threadsrc/java-runtime/java-runtime.targets
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 3, 2026
@simonrozsivalsimonrozsival changed the title Use trimmable Java proxy runtime sources[TrimmableTypeMap] Use trimmable Java proxy runtime sourcesMay 3, 2026
Base automatically changed from trimmable-typemap-startup-fixes to mainMay 4, 2026 15:17
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from 1467afa to e66930eCompareMay 4, 2026 18:21
simonrozsivaland others added 2 commits May 4, 2026 20:31
Add trimmable-specific java_runtime jars that replace Java.Interop's JavaProxyObject and JavaProxyThrowable sources only for the trimmable typemap path. Keep the existing runtime jars on Java.Interop's native-registration behavior and select the trimmable jars when _AndroidTypeMapImplementation is trimmable.
Re-enable the affected Java.Interop runtime tests and add focused coverage for JavaProxyObject marshaling/object methods under the trimmable typemap path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add comments documenting runtime jar selection and Java proxy identity semantics.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from e66930e to 0644b70CompareMay 4, 2026 18:31
@simonrozsival
simonrozsival marked this pull request as ready for review May 5, 2026 09:31
CopilotAI review requested due to automatic review settings May 5, 2026 09:31

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 updates the trimmable typemap path to use trimmable-specific Java runtime sources for JavaProxyObject / JavaProxyThrowable, selecting new runtime jars only when _AndroidTypeMapImplementation=trimmable, and re-enables previously excluded Java.Interop tests by adding targeted validation for the new proxy behavior.

Changes:

  • Add trimmable Java runtime proxy sources (src/java-runtime/java-trimmable/...) and build new runtime jar/dex variants for both MonoVM and CoreCLR.
  • Update MSBuild runtime-jar selection logic to choose trimmable vs non-trimmable runtime jars based on _AndroidRuntime × _AndroidTypeMapImplementation.
  • Re-enable previously excluded Java.Interop tests and add focused trimmable coverage around Java proxy marshaling and object-method semantics.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.csRemoves prior trimmable exclusions now that trimmable proxy classes are provided.
tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.csAdds new tests validating marshaling and Java-side JavaProxyObject behavior under trimmable typemap.
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targetsSelects trimmable vs non-trimmable runtime jar based on runtime + typemap implementation.
src/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyThrowable.javaIntroduces trimmable-specific Java proxy throwable implementation.
src/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyObject.javaIntroduces trimmable-specific Java proxy object implementation (no native registration; identity semantics).
src/java-runtime/java-runtime.targetsBuilds additional trimmable runtime jar/dex outputs and improves incremental inputs / stale classes.dex cleanup.
build-tools/installers/create-installers.targetsShips the new trimmable runtime jar/dex artifacts in installers.

Comment threadsrc/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyObject.java Outdated
Use repository Java formatting for trimmable proxy sources and strengthen the proxy hashCode test so it compares against Java identityHashCode instead of itself.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot resolve the merge conflicts in this pull request

CopilotAI commented May 6, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

The merge conflicts are resolved locally:

  • TrimmableTypeMapTypeManagerTests.cs: kept both our JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics test and main's new TryGetArrayType_PrimitiveLeaf_DoesNotRequireRankMapEntry test from [TrimmableTypeMap] Improve array handling #11238.
  • NUnitInstrumentation.cs: kept our HEAD version (the JavaProxyObject/JavaProxyThrowable test exclusions were removed by this PR since the trimmable runtime jar fixes those issues — discarding main's re-addition of them).

However, the push is being rejected by the Xamarin.Android-PR required status check rule (the merge commit's SHA hasn't had CI run against it yet). Could you push the branch manually or trigger CI to unblock? The local merge commit is 4ed4581.

…object
# Conflicts:
#	tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.cs
#	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

MAUI tests are currently broken: #11302

@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 7, 2026
Comment threadsrc/java-runtime/java-runtime.targets Outdated
Comment threadbuild-tools/installers/create-installers.targets Outdated
Drop stale _net6 Java runtime artifact names and collapse the trimmable runtime jar/dex to a single shared artifact for CoreCLR and NativeAOT.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment on lines +42 to +54
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_clr.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_clr.dex" />
</ItemGroup>

<Target Name="_DeleteObsoleteJavaRuntimeArtifacts" BeforeTargets="_BuildJavaRuntimeJar">
<Delete Files="@(_ObsoleteRuntimeOutput)" />
</Target>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We probably don't have to delete these, we could just leave them.

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.

@copilot remove this unnecessary Target and the _ObsoleteRuntimeOutput item.

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.

Done — removed the _ObsoleteRuntimeOutput item group, the _DeleteObsoleteJavaRuntimeArtifacts target, and the leftover @(_ObsoleteRuntimeOutput) reference in _CleanJavaRuntimeJar. The changes are in the local commit but push is blocked by the required CI status check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsival merged commit 22e2966 into mainMay 11, 2026
3 checks passed
@simonrozsival
simonrozsival deleted the trimmable-java-proxy-object branch May 11, 2026 07:16
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 10, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

copilot`copilot-cli` or other AIs were used to author thisready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).trimmable-type-map

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[TrimmableTypeMap] Use trimmable Java proxy runtime sources - #11271

Merged
simonrozsival merged 8 commits into
mainfrom
trimmable-java-proxy-object
May 11, 2026
Merged

[TrimmableTypeMap] Use trimmable Java proxy runtime sources#11271
simonrozsival merged 8 commits into
mainfrom
trimmable-java-proxy-object

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented May 3, 2026

Copy link
Copy Markdown
Member

Summary

  • add trimmable-specific runtime jars (java_runtime_trimmable_net6.jar and java_runtime_trimmable_clr.jar) that replace Java.Interop's incompatible JavaProxyObject.java / JavaProxyThrowable.java only for _AndroidTypeMapImplementation=trimmable
  • keep the existing non-trimmable runtime jars on Java.Interop's native-registration behavior; _net6 follows the existing historical non-CoreCLR runtime jar naming (java_runtime_net6.jar), not the current .NET TFM
  • include the new trimmable jar/dex outputs in installer file lists and make java-runtime incremental builds account for java-trimmable sources
  • re-enable the affected Java.Interop tests and add focused trimmable JavaProxyObject coverage

Validation

  • dotnet build src/java-runtime/java-runtime.csproj -v:minimal
  • dotnet build src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj -v:minimal
  • dotnet build src/Mono.Android/Mono.Android.csproj -v:minimal
  • MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj -c Debug -p:_AndroidTypeMapImplementation=trimmable -nr:false
  • dotnet test tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests.csproj -v minimal
  • trimmable device instrumentation: 900 passed, 0 failed
  • verified normal runtime jars keep native JavaProxyObject registration, trimmable runtime jars have direct Java object methods and no static native registration

Related issues

@simonrozsival
simonrozsival changed the base branch from main to trimmable-typemap-startup-fixesMay 3, 2026 07:22
@simonrozsival
simonrozsival changed the base branch from trimmable-typemap-startup-fixes to mainMay 3, 2026 07:22
@simonrozsival
simonrozsival changed the base branch from main to trimmable-typemap-startup-fixesMay 3, 2026 07:26
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@github-actions

github-actionsBot commented May 3, 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.

✅ LGTM — Clean, well-structured change

Summary: Introduces trimmable-specific Java runtime jars that replace Java.Interop's JavaProxyObject.java / JavaProxyThrowable.java with versions that don't call ManagedPeer.registerNativeMembers(). This fixes the root cause behind #11170 by providing Java identity implementations of equals/hashCode/toString instead of native methods.

What I verified

  • _AndroidTypeMapImplementation is already in _PropertyCacheItems (line 996), so incremental builds correctly invalidate when switching typemap implementations
  • ✅ The 4-way condition matrix in _CollectRuntimeJarFilenames covers all combinations exhaustively (MonoVM × CoreCLR × default × trimmable)
  • _RuntimeOutput.AddItems metadata is properly added to Inputs for incremental build tracking
  • ✅ The Delete of stale classes.dex prevents D8 output from leaking into jars during incremental builds
  • ✅ New Java files correctly mirror the original Java.Interop implementations minus the static { registerNativeMembers() } block and native method declarations
  • ✅ Installer file lists include all 4 new artifacts (trimmable jar+dex for net6 and clr)
  • ✅ Re-enabled tests (previously excluded due to registerNativeMembers failure) are now validated by 900 passing device tests
  • ✅ New test coverage validates proxy type, object array usage, and Java identity semantics

Positive callouts

  • The RemoveItems/AddItems metadata pattern on _RuntimeOutput is a clean approach to source file swapping — it keeps the build logic centralized in the target without needing separate targets
  • Good test for JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics that explicitly verifies the behavioral contract of the trimmable proxy
  • Removing 27 lines of test exclusions from NUnitInstrumentation.cs is a nice cleanup

CI

The PR is in draft status. The dotnet-android check shows neutral (not yet run). CI results should be verified before merging.

3 💡 suggestions posted inline — all documentation/clarity improvements, no required changes.

Generated by Android PR Reviewer for issue #11271 · ● 6.2M

Comment threadsrc/java-runtime/java-runtime.targets
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 3, 2026
@simonrozsivalsimonrozsival changed the title Use trimmable Java proxy runtime sources[TrimmableTypeMap] Use trimmable Java proxy runtime sourcesMay 3, 2026
Base automatically changed from trimmable-typemap-startup-fixes to mainMay 4, 2026 15:17
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from 1467afa to e66930eCompareMay 4, 2026 18:21
simonrozsivaland others added 2 commits May 4, 2026 20:31
Add trimmable-specific java_runtime jars that replace Java.Interop's JavaProxyObject and JavaProxyThrowable sources only for the trimmable typemap path. Keep the existing runtime jars on Java.Interop's native-registration behavior and select the trimmable jars when _AndroidTypeMapImplementation is trimmable.
Re-enable the affected Java.Interop runtime tests and add focused coverage for JavaProxyObject marshaling/object methods under the trimmable typemap path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add comments documenting runtime jar selection and Java proxy identity semantics.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from e66930e to 0644b70CompareMay 4, 2026 18:31
@simonrozsival
simonrozsival marked this pull request as ready for review May 5, 2026 09:31
CopilotAI review requested due to automatic review settings May 5, 2026 09:31

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 updates the trimmable typemap path to use trimmable-specific Java runtime sources for JavaProxyObject / JavaProxyThrowable, selecting new runtime jars only when _AndroidTypeMapImplementation=trimmable, and re-enables previously excluded Java.Interop tests by adding targeted validation for the new proxy behavior.

Changes:

  • Add trimmable Java runtime proxy sources (src/java-runtime/java-trimmable/...) and build new runtime jar/dex variants for both MonoVM and CoreCLR.
  • Update MSBuild runtime-jar selection logic to choose trimmable vs non-trimmable runtime jars based on _AndroidRuntime × _AndroidTypeMapImplementation.
  • Re-enable previously excluded Java.Interop tests and add focused trimmable coverage around Java proxy marshaling and object-method semantics.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.csRemoves prior trimmable exclusions now that trimmable proxy classes are provided.
tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.csAdds new tests validating marshaling and Java-side JavaProxyObject behavior under trimmable typemap.
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targetsSelects trimmable vs non-trimmable runtime jar based on runtime + typemap implementation.
src/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyThrowable.javaIntroduces trimmable-specific Java proxy throwable implementation.
src/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyObject.javaIntroduces trimmable-specific Java proxy object implementation (no native registration; identity semantics).
src/java-runtime/java-runtime.targetsBuilds additional trimmable runtime jar/dex outputs and improves incremental inputs / stale classes.dex cleanup.
build-tools/installers/create-installers.targetsShips the new trimmable runtime jar/dex artifacts in installers.

Comment threadsrc/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyObject.java Outdated
Use repository Java formatting for trimmable proxy sources and strengthen the proxy hashCode test so it compares against Java identityHashCode instead of itself.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot resolve the merge conflicts in this pull request

CopilotAI commented May 6, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

The merge conflicts are resolved locally:

  • TrimmableTypeMapTypeManagerTests.cs: kept both our JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics test and main's new TryGetArrayType_PrimitiveLeaf_DoesNotRequireRankMapEntry test from [TrimmableTypeMap] Improve array handling #11238.
  • NUnitInstrumentation.cs: kept our HEAD version (the JavaProxyObject/JavaProxyThrowable test exclusions were removed by this PR since the trimmable runtime jar fixes those issues — discarding main's re-addition of them).

However, the push is being rejected by the Xamarin.Android-PR required status check rule (the merge commit's SHA hasn't had CI run against it yet). Could you push the branch manually or trigger CI to unblock? The local merge commit is 4ed4581.

…object
# Conflicts:
#	tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.cs
#	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

MAUI tests are currently broken: #11302

@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 7, 2026
Comment threadsrc/java-runtime/java-runtime.targets Outdated
Comment threadbuild-tools/installers/create-installers.targets Outdated
Drop stale _net6 Java runtime artifact names and collapse the trimmable runtime jar/dex to a single shared artifact for CoreCLR and NativeAOT.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment on lines +42 to +54
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_clr.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_clr.dex" />
</ItemGroup>

<Target Name="_DeleteObsoleteJavaRuntimeArtifacts" BeforeTargets="_BuildJavaRuntimeJar">
<Delete Files="@(_ObsoleteRuntimeOutput)" />
</Target>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We probably don't have to delete these, we could just leave them.

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.

@copilot remove this unnecessary Target and the _ObsoleteRuntimeOutput item.

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.

Done — removed the _ObsoleteRuntimeOutput item group, the _DeleteObsoleteJavaRuntimeArtifacts target, and the leftover @(_ObsoleteRuntimeOutput) reference in _CleanJavaRuntimeJar. The changes are in the local commit but push is blocked by the required CI status check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsival merged commit 22e2966 into mainMay 11, 2026
3 checks passed
@simonrozsival
simonrozsival deleted the trimmable-java-proxy-object branch May 11, 2026 07:16
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 10, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

copilot`copilot-cli` or other AIs were used to author thisready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).trimmable-type-map

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

[TrimmableTypeMap] Use trimmable Java proxy runtime sources - #11271

Merged
simonrozsival merged 8 commits into
mainfrom
trimmable-java-proxy-object
May 11, 2026
Merged

[TrimmableTypeMap] Use trimmable Java proxy runtime sources#11271
simonrozsival merged 8 commits into
mainfrom
trimmable-java-proxy-object

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented May 3, 2026

Copy link
Copy Markdown
Member

Summary

  • add trimmable-specific runtime jars (java_runtime_trimmable_net6.jar and java_runtime_trimmable_clr.jar) that replace Java.Interop's incompatible JavaProxyObject.java / JavaProxyThrowable.java only for _AndroidTypeMapImplementation=trimmable
  • keep the existing non-trimmable runtime jars on Java.Interop's native-registration behavior; _net6 follows the existing historical non-CoreCLR runtime jar naming (java_runtime_net6.jar), not the current .NET TFM
  • include the new trimmable jar/dex outputs in installer file lists and make java-runtime incremental builds account for java-trimmable sources
  • re-enable the affected Java.Interop tests and add focused trimmable JavaProxyObject coverage

Validation

  • dotnet build src/java-runtime/java-runtime.csproj -v:minimal
  • dotnet build src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj -v:minimal
  • dotnet build src/Mono.Android/Mono.Android.csproj -v:minimal
  • MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj -c Debug -p:_AndroidTypeMapImplementation=trimmable -nr:false
  • dotnet test tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests.csproj -v minimal
  • trimmable device instrumentation: 900 passed, 0 failed
  • verified normal runtime jars keep native JavaProxyObject registration, trimmable runtime jars have direct Java object methods and no static native registration

Related issues

@simonrozsival
simonrozsival changed the base branch from main to trimmable-typemap-startup-fixesMay 3, 2026 07:22
@simonrozsival
simonrozsival changed the base branch from trimmable-typemap-startup-fixes to mainMay 3, 2026 07:22
@simonrozsival
simonrozsival changed the base branch from main to trimmable-typemap-startup-fixesMay 3, 2026 07:26
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@github-actions

github-actionsBot commented May 3, 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.

✅ LGTM — Clean, well-structured change

Summary: Introduces trimmable-specific Java runtime jars that replace Java.Interop's JavaProxyObject.java / JavaProxyThrowable.java with versions that don't call ManagedPeer.registerNativeMembers(). This fixes the root cause behind #11170 by providing Java identity implementations of equals/hashCode/toString instead of native methods.

What I verified

  • _AndroidTypeMapImplementation is already in _PropertyCacheItems (line 996), so incremental builds correctly invalidate when switching typemap implementations
  • ✅ The 4-way condition matrix in _CollectRuntimeJarFilenames covers all combinations exhaustively (MonoVM × CoreCLR × default × trimmable)
  • _RuntimeOutput.AddItems metadata is properly added to Inputs for incremental build tracking
  • ✅ The Delete of stale classes.dex prevents D8 output from leaking into jars during incremental builds
  • ✅ New Java files correctly mirror the original Java.Interop implementations minus the static { registerNativeMembers() } block and native method declarations
  • ✅ Installer file lists include all 4 new artifacts (trimmable jar+dex for net6 and clr)
  • ✅ Re-enabled tests (previously excluded due to registerNativeMembers failure) are now validated by 900 passing device tests
  • ✅ New test coverage validates proxy type, object array usage, and Java identity semantics

Positive callouts

  • The RemoveItems/AddItems metadata pattern on _RuntimeOutput is a clean approach to source file swapping — it keeps the build logic centralized in the target without needing separate targets
  • Good test for JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics that explicitly verifies the behavioral contract of the trimmable proxy
  • Removing 27 lines of test exclusions from NUnitInstrumentation.cs is a nice cleanup

CI

The PR is in draft status. The dotnet-android check shows neutral (not yet run). CI results should be verified before merging.

3 💡 suggestions posted inline — all documentation/clarity improvements, no required changes.

Generated by Android PR Reviewer for issue #11271 · ● 6.2M

Comment threadsrc/java-runtime/java-runtime.targets
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 3, 2026
@simonrozsivalsimonrozsival changed the title Use trimmable Java proxy runtime sources[TrimmableTypeMap] Use trimmable Java proxy runtime sourcesMay 3, 2026
Base automatically changed from trimmable-typemap-startup-fixes to mainMay 4, 2026 15:17
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from 1467afa to e66930eCompareMay 4, 2026 18:21
simonrozsivaland others added 2 commits May 4, 2026 20:31
Add trimmable-specific java_runtime jars that replace Java.Interop's JavaProxyObject and JavaProxyThrowable sources only for the trimmable typemap path. Keep the existing runtime jars on Java.Interop's native-registration behavior and select the trimmable jars when _AndroidTypeMapImplementation is trimmable.
Re-enable the affected Java.Interop runtime tests and add focused coverage for JavaProxyObject marshaling/object methods under the trimmable typemap path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add comments documenting runtime jar selection and Java proxy identity semantics.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from e66930e to 0644b70CompareMay 4, 2026 18:31
@simonrozsival
simonrozsival marked this pull request as ready for review May 5, 2026 09:31
CopilotAI review requested due to automatic review settings May 5, 2026 09:31

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 updates the trimmable typemap path to use trimmable-specific Java runtime sources for JavaProxyObject / JavaProxyThrowable, selecting new runtime jars only when _AndroidTypeMapImplementation=trimmable, and re-enables previously excluded Java.Interop tests by adding targeted validation for the new proxy behavior.

Changes:

  • Add trimmable Java runtime proxy sources (src/java-runtime/java-trimmable/...) and build new runtime jar/dex variants for both MonoVM and CoreCLR.
  • Update MSBuild runtime-jar selection logic to choose trimmable vs non-trimmable runtime jars based on _AndroidRuntime × _AndroidTypeMapImplementation.
  • Re-enable previously excluded Java.Interop tests and add focused trimmable coverage around Java proxy marshaling and object-method semantics.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.csRemoves prior trimmable exclusions now that trimmable proxy classes are provided.
tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.csAdds new tests validating marshaling and Java-side JavaProxyObject behavior under trimmable typemap.
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targetsSelects trimmable vs non-trimmable runtime jar based on runtime + typemap implementation.
src/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyThrowable.javaIntroduces trimmable-specific Java proxy throwable implementation.
src/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyObject.javaIntroduces trimmable-specific Java proxy object implementation (no native registration; identity semantics).
src/java-runtime/java-runtime.targetsBuilds additional trimmable runtime jar/dex outputs and improves incremental inputs / stale classes.dex cleanup.
build-tools/installers/create-installers.targetsShips the new trimmable runtime jar/dex artifacts in installers.

Comment threadsrc/java-runtime/java-trimmable/net/dot/jni/internal/JavaProxyObject.java Outdated
Use repository Java formatting for trimmable proxy sources and strengthen the proxy hashCode test so it compares against Java identityHashCode instead of itself.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot resolve the merge conflicts in this pull request

CopilotAI commented May 6, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

The merge conflicts are resolved locally:

  • TrimmableTypeMapTypeManagerTests.cs: kept both our JavaProxyObject_ObjectMethodsUseJavaIdentitySemantics test and main's new TryGetArrayType_PrimitiveLeaf_DoesNotRequireRankMapEntry test from [TrimmableTypeMap] Improve array handling #11238.
  • NUnitInstrumentation.cs: kept our HEAD version (the JavaProxyObject/JavaProxyThrowable test exclusions were removed by this PR since the trimmable runtime jar fixes those issues — discarding main's re-addition of them).

However, the push is being rejected by the Xamarin.Android-PR required status check rule (the merge commit's SHA hasn't had CI run against it yet). Could you push the branch manually or trigger CI to unblock? The local merge commit is 4ed4581.

…object
# Conflicts:
#	tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.cs
#	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

MAUI tests are currently broken: #11302

@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 7, 2026
Comment threadsrc/java-runtime/java-runtime.targets Outdated
Comment threadbuild-tools/installers/create-installers.targets Outdated
Drop stale _net6 Java runtime artifact names and collapse the trimmable runtime jar/dex to a single shared artifact for CoreCLR and NativeAOT.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment on lines +42 to +54
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_net6.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_net6.dex" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_clr.jar" />
<_ObsoleteRuntimeOutput Include="$(OutputPath)java_runtime_trimmable_clr.dex" />
</ItemGroup>

<Target Name="_DeleteObsoleteJavaRuntimeArtifacts" BeforeTargets="_BuildJavaRuntimeJar">
<Delete Files="@(_ObsoleteRuntimeOutput)" />
</Target>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We probably don't have to delete these, we could just leave them.

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.

@copilot remove this unnecessary Target and the _ObsoleteRuntimeOutput item.

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.

Done — removed the _ObsoleteRuntimeOutput item group, the _DeleteObsoleteJavaRuntimeArtifacts target, and the leftover @(_ObsoleteRuntimeOutput) reference in _CleanJavaRuntimeJar. The changes are in the local commit but push is blocked by the required CI status check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsival merged commit 22e2966 into mainMay 11, 2026
3 checks passed
@simonrozsival
simonrozsival deleted the trimmable-java-proxy-object branch May 11, 2026 07:16
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 10, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

copilot`copilot-cli` or other AIs were used to author thisready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).trimmable-type-map

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers