[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251 - #11274

Merged
jonathanpeppers merged 21 commits into
mainfrom
trimmable-virtual-constructor
May 14, 2026
Merged

[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251#11274
jonathanpeppers merged 21 commits into
mainfrom
trimmable-virtual-constructor

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented May 3, 2026

Copy link
Copy Markdown
Member

Refuses [JniAddNativeMethodRegistrationAttribute] in the trimmable typemap.

[JniAddNativeMethodRegistrationAttribute] is a legacy Java.Interop public API. Its primary consumer — the jnimarshalmethod-gen build-time generator that used to emit [JniAddNativeMethodRegistrationAttribute] static void __RegisterNativeMembers stubs on every JCW type — was removed in dotnet/java-interop#1405. The only remaining in-tree uses are Java.Interop's own JavaProxyObject / JavaProxyThrowable infrastructure types (already bypassed in the trimmable path by #11271) and a couple of upstream Java.Interop test fixtures. Supporting it in the trimmable typemap would mean adding scanner + ModelBuilder support for an obsolete code path with no in-tree consumers and a near-zero customer base.

This PR makes the design decision explicit:

  • JavaPeerScanner now takes an optional ITrimmableTypeMapLogger. When it encounters [JniAddNativeMethodRegistrationAttribute] on any method, it calls ITrimmableTypeMapLogger.LogJniAddNativeMethodRegistrationAttributeError directly from the per-type scan loop. No JavaPeerInfo property is propagated; the orchestrator simply passes its logger into new JavaPeerScanner(logger).
  • The MSBuild logger maps the call to XA4251, so GenerateTrimmableTypeMap fails the build via TaskLoggingHelper.HasLoggedErrors.
  • The message instructs developers to either avoid the attribute or switch off the trimmable typemap (for example, by using the llvm-ir type map implementation), and to report the scenario at https://github.com/dotnet/android/issues so the team can evaluate whether to support it.
  • Java.InteropTests.InvokeVirtualFromConstructorTests (which uses the attribute) is permanently excluded under the trimmable typemap with an explanatory comment pointing at this policy.
  • tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csproj excludes the upstream CallVirtualFromConstructor{Base,Derived}.cs and InvokeVirtualFromConstructorTests.cs from the test assembly compile when _AndroidTypeMapImplementation == trimmable, so the device-test build can compile through the trimmable typemap generator. (The other upstream user of the attribute, TestType.cs, is already gated by #if !NO_MARSHAL_MEMBER_BUILDER_SUPPORT, which the test csproj defines.)

Tests:

  • JavaPeerScannerTests.Scan_JniAddNativeMethodRegistrationAttribute_LogsError (new) gives the scanner a recording ITrimmableTypeMapLogger and asserts it logs XA4251 for HandWrittenNativeRegistrationPeer and not for unrelated fixture types.
  • TrimmableTypeMapGeneratorTests.Execute_WithJniAddNativeMethodRegistrationAttribute_ReportsXA4251 (new) verifies the orchestrator end-to-end emits XA4251 against the same fixture.

Device validation against an Android emulator with the CoreCLRTrimmable lane:

ANDROID_SERIAL=emulator-5554 MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build \
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj \
-t:RunTestApp -c Release \
-p:_AndroidTypeMapImplementation=trimmable -p:UseMonoRuntime=false \
-nr:false -m:1

TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total, 0 errors, 0 failures, 21 ignored.

Related issues

@simonrozsivalsimonrozsival changed the title Use trimmable virtual-constructor fixtures[TrimmableTypeMap] Use trimmable virtual-constructor fixturesMay 3, 2026
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 3, 2026
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from 1467afa to e66930eCompareMay 4, 2026 18:21
@simonrozsival
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 711aeae to 7e2737bCompareMay 4, 2026 18:23
simonrozsivaland others added 3 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>
Enable the Java.Interop virtual-constructor tests in the trimmable typemap lane by swapping in Android-owned Java fixtures that use Runtime.registerNatives and generated n_* callbacks instead of ManagedPeer.
Teach the trimmable typemap scanner/model to emit native registrations for hand-written Java peers that opt into JniAddNativeMethodRegistrationAttribute.
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
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 7e2737b to dc13b42CompareMay 4, 2026 18:31
simonrozsivaland others added 7 commits May 5, 2026 11:31
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>
…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
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>
Base automatically changed from trimmable-java-proxy-object to mainMay 11, 2026 07:16
…structor
# Conflicts:
#	src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs
#	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs
@simonrozsival
simonrozsival marked this pull request as ready for review May 11, 2026 09:11
CopilotAI review requested due to automatic review settings May 11, 2026 09:11
…mmableTypeMapBuildTests
This cleanup is not related to fixing InvokeVirtualFromConstructorTests
and belongs in a separate change.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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 re-enables Java.InteropTests.InvokeVirtualFromConstructorTests for the CoreCLR trimmable typemap lane by swapping desktop-JVM Java.Interop fixtures for Android/trimmable-compatible copies and extending the trimmable typemap generator to support native registrations for hand-written Java peers.

Changes:

  • Removes the trimmable-typemap exclusion for Java.InteropTests.InvokeVirtualFromConstructorTests and adds trimmable Java/C# fixtures for CallVirtualFromConstructor*.
  • Extends the trimmable typemap scanner/model to detect JniAddNativeMethodRegistrationAttribute usage and emit proxy/registration support accordingly.
  • Adds cleanup/validation for obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts (delete during build; assert not packaged in SDK tests).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.csRe-enables InvokeVirtualFromConstructorTests by removing its name-based exclusion.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-trimmable/CallVirtualFromConstructorDerived.csAdds trimmable managed peer fixture using generated n_* callbacks + JniAddNativeMethodRegistrationAttribute.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.targetsSwitches trimmable builds to include Android-owned Java fixtures in the test JAR and exclude the desktop versions.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csprojConditionally swaps the managed CallVirtualFromConstructorDerived source between desktop and trimmable variants.
tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorDerived.javaAdds Android/trimmable Java fixture using mono.android.Runtime.registerNatives(Class) via reflection.
tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorBase.javaAdds Android/trimmable base Java fixture using registerNatives(Class) via reflection.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.csVerifies obsolete net6/trimmable_clr runtime artifacts are not shipped in the SDK pack.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.csDetects method-level JniAddNativeMethodRegistrationAttribute to inform generation decisions.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerInfo.csStores whether a peer uses JniAddNativeMethodRegistrationAttribute.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.csTreats certain DoNotGenerateAcw peers with native registrations as needing proxy/registration emission.
src/java-runtime/java-runtime.targetsDeletes obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts during build/clean.

Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Outdated
…emap
[JniAddNativeMethodRegistrationAttribute] is a legacy Java.Interop API whose
primary consumer — the jnimarshalmethod-gen build-time generator — was
removed in dotnet/java-interop#1405. The trimmable typemap deliberately does
not support this attribute.
When the scanner detects the attribute on any method, the generator emits
XA4251 telling the developer to either avoid it or switch off the trimmable
typemap (for example, by using the 'llvm-ir' type map implementation) and
report the scenario at https://github.com/dotnet/android/issues. The build
fails via TaskLoggingHelper.HasLoggedErrors.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival changed the title [TrimmableTypeMap] Use trimmable virtual-constructor fixtures[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251May 11, 2026
simonrozsivaland others added 3 commits May 11, 2026 12:05
Address review feedback:
- Drop JavaPeerInfo.HasJniAddNativeMethodRegistrationAttribute. The scanner
now takes an optional ITrimmableTypeMapLogger and reports XA4251 directly
when it encounters the attribute, instead of propagating a bool the rest
of the pipeline doesn't otherwise need.
- Drop the orchestrator's post-scan loop; TrimmableTypeMapGenerator just
passes its logger into JavaPeerScanner.
- Reset external/Java.Interop and external/xamarin-android-tools to the
SHAs on main; this PR doesn't need either submodule moved.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t/dot/jni/test/GetThis.java
This file is unrelated to the XA4251 work; it was accidentally removed during
an earlier 'git rm -r java-trimmable' cleanup. It's still needed by
JavaObjectTest.DisposeAccessesThis under the trimmable typemap.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The upstream Java.Interop test fixture CallVirtualFromConstructorDerived
uses [JniAddNativeMethodRegistrationAttribute]. Now that the trimmable
typemap refuses that attribute with XA4251, the offending sources need to
be excluded from the test assembly when building for the trimmable type
map; otherwise the build cannot reach the device tests at all.
Validated locally:
ANDROID_SERIAL=emulator-5554 MSBUILDDISABLENODEREUSE=1 \
./dotnet-local.sh build \
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj \
-t:RunTestApp -c Release \
-p:_AndroidTypeMapImplementation=trimmable \
-p:UseMonoRuntime=false -nr:false -m:1
TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total,
0 errors, 0 failures, 21 ignored.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Code-review caught that the prior placement of the XA4251 check sat *after*
the scanner's per-type filtering, so a type carrying the attribute but no
[Register] (and not extending a Java peer) would slip past the diagnostic
and the build would silently succeed.
Hoist the check to immediately after the <Module> skip so it fires uniformly
for every non-<Module> type, regardless of whether the type would otherwise
have been added to the typemap. Add a NonPeerNativeRegistration fixture to
the scanner test to guard the regression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 7ad46cf to 7d607c5CompareMay 11, 2026 10:53
…bute
Address Copilot reviewer feedback on the per-type method-attribute walk.
AssemblyIndex.Build now does a cheap pass over the TypeReferences and
TypeDefinitions tables to set MayUseJniAddNativeMethodRegistrationAttribute,
and the scanner short-circuits the per-method walk in the overwhelmingly
common case where the assembly neither imports nor declares the attribute.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
simonrozsival added a commit that referenced this pull request May 11, 2026
Squashed prerequisites from PR #11274 (trimmable-virtual-constructor):
reject [JniAddNativeMethodRegistrationAttribute] with XA4251 in the
trimmable typemap path and exclude the upstream
InvokeVirtualFromConstructor fixtures so the trimmable test assembly
builds.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 12, 2026
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Outdated
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Outdated
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Outdated
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot address reviewer's comments

CopilotAI commented May 13, 2026

Copy link
Copy Markdown
Contributor

@copilot address reviewer's comments

Addressed the reviewer feedback with namespace-aware matching in both the fast-check and per-method attribute match, plus regression coverage for same-name attributes in other namespaces. See commits d779cec and ed91def.

simonrozsivaland others added 2 commits May 13, 2026 14:24
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve merge conflicts: combine packageNamingPolicy and logger
parameters in JavaPeerScanner constructor.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jonathanpeppers
jonathanpeppers merged commit 61a5839 into mainMay 14, 2026
3 checks passed
@jonathanpeppers
jonathanpeppers deleted the trimmable-virtual-constructor branch May 14, 2026 20:53
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 14, 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 thisnice-to-haveready-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] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251 - #11274

Merged
jonathanpeppers merged 21 commits into
mainfrom
trimmable-virtual-constructor
May 14, 2026
Merged

[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251#11274
jonathanpeppers merged 21 commits into
mainfrom
trimmable-virtual-constructor

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented May 3, 2026

Copy link
Copy Markdown
Member

Refuses [JniAddNativeMethodRegistrationAttribute] in the trimmable typemap.

[JniAddNativeMethodRegistrationAttribute] is a legacy Java.Interop public API. Its primary consumer — the jnimarshalmethod-gen build-time generator that used to emit [JniAddNativeMethodRegistrationAttribute] static void __RegisterNativeMembers stubs on every JCW type — was removed in dotnet/java-interop#1405. The only remaining in-tree uses are Java.Interop's own JavaProxyObject / JavaProxyThrowable infrastructure types (already bypassed in the trimmable path by #11271) and a couple of upstream Java.Interop test fixtures. Supporting it in the trimmable typemap would mean adding scanner + ModelBuilder support for an obsolete code path with no in-tree consumers and a near-zero customer base.

This PR makes the design decision explicit:

  • JavaPeerScanner now takes an optional ITrimmableTypeMapLogger. When it encounters [JniAddNativeMethodRegistrationAttribute] on any method, it calls ITrimmableTypeMapLogger.LogJniAddNativeMethodRegistrationAttributeError directly from the per-type scan loop. No JavaPeerInfo property is propagated; the orchestrator simply passes its logger into new JavaPeerScanner(logger).
  • The MSBuild logger maps the call to XA4251, so GenerateTrimmableTypeMap fails the build via TaskLoggingHelper.HasLoggedErrors.
  • The message instructs developers to either avoid the attribute or switch off the trimmable typemap (for example, by using the llvm-ir type map implementation), and to report the scenario at https://github.com/dotnet/android/issues so the team can evaluate whether to support it.
  • Java.InteropTests.InvokeVirtualFromConstructorTests (which uses the attribute) is permanently excluded under the trimmable typemap with an explanatory comment pointing at this policy.
  • tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csproj excludes the upstream CallVirtualFromConstructor{Base,Derived}.cs and InvokeVirtualFromConstructorTests.cs from the test assembly compile when _AndroidTypeMapImplementation == trimmable, so the device-test build can compile through the trimmable typemap generator. (The other upstream user of the attribute, TestType.cs, is already gated by #if !NO_MARSHAL_MEMBER_BUILDER_SUPPORT, which the test csproj defines.)

Tests:

  • JavaPeerScannerTests.Scan_JniAddNativeMethodRegistrationAttribute_LogsError (new) gives the scanner a recording ITrimmableTypeMapLogger and asserts it logs XA4251 for HandWrittenNativeRegistrationPeer and not for unrelated fixture types.
  • TrimmableTypeMapGeneratorTests.Execute_WithJniAddNativeMethodRegistrationAttribute_ReportsXA4251 (new) verifies the orchestrator end-to-end emits XA4251 against the same fixture.

Device validation against an Android emulator with the CoreCLRTrimmable lane:

ANDROID_SERIAL=emulator-5554 MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build \
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj \
-t:RunTestApp -c Release \
-p:_AndroidTypeMapImplementation=trimmable -p:UseMonoRuntime=false \
-nr:false -m:1

TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total, 0 errors, 0 failures, 21 ignored.

Related issues

@simonrozsivalsimonrozsival changed the title Use trimmable virtual-constructor fixtures[TrimmableTypeMap] Use trimmable virtual-constructor fixturesMay 3, 2026
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 3, 2026
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from 1467afa to e66930eCompareMay 4, 2026 18:21
@simonrozsival
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 711aeae to 7e2737bCompareMay 4, 2026 18:23
simonrozsivaland others added 3 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>
Enable the Java.Interop virtual-constructor tests in the trimmable typemap lane by swapping in Android-owned Java fixtures that use Runtime.registerNatives and generated n_* callbacks instead of ManagedPeer.
Teach the trimmable typemap scanner/model to emit native registrations for hand-written Java peers that opt into JniAddNativeMethodRegistrationAttribute.
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
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 7e2737b to dc13b42CompareMay 4, 2026 18:31
simonrozsivaland others added 7 commits May 5, 2026 11:31
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>
…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
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>
Base automatically changed from trimmable-java-proxy-object to mainMay 11, 2026 07:16
…structor
# Conflicts:
#	src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs
#	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs
@simonrozsival
simonrozsival marked this pull request as ready for review May 11, 2026 09:11
CopilotAI review requested due to automatic review settings May 11, 2026 09:11
…mmableTypeMapBuildTests
This cleanup is not related to fixing InvokeVirtualFromConstructorTests
and belongs in a separate change.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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 re-enables Java.InteropTests.InvokeVirtualFromConstructorTests for the CoreCLR trimmable typemap lane by swapping desktop-JVM Java.Interop fixtures for Android/trimmable-compatible copies and extending the trimmable typemap generator to support native registrations for hand-written Java peers.

Changes:

  • Removes the trimmable-typemap exclusion for Java.InteropTests.InvokeVirtualFromConstructorTests and adds trimmable Java/C# fixtures for CallVirtualFromConstructor*.
  • Extends the trimmable typemap scanner/model to detect JniAddNativeMethodRegistrationAttribute usage and emit proxy/registration support accordingly.
  • Adds cleanup/validation for obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts (delete during build; assert not packaged in SDK tests).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.csRe-enables InvokeVirtualFromConstructorTests by removing its name-based exclusion.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-trimmable/CallVirtualFromConstructorDerived.csAdds trimmable managed peer fixture using generated n_* callbacks + JniAddNativeMethodRegistrationAttribute.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.targetsSwitches trimmable builds to include Android-owned Java fixtures in the test JAR and exclude the desktop versions.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csprojConditionally swaps the managed CallVirtualFromConstructorDerived source between desktop and trimmable variants.
tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorDerived.javaAdds Android/trimmable Java fixture using mono.android.Runtime.registerNatives(Class) via reflection.
tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorBase.javaAdds Android/trimmable base Java fixture using registerNatives(Class) via reflection.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.csVerifies obsolete net6/trimmable_clr runtime artifacts are not shipped in the SDK pack.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.csDetects method-level JniAddNativeMethodRegistrationAttribute to inform generation decisions.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerInfo.csStores whether a peer uses JniAddNativeMethodRegistrationAttribute.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.csTreats certain DoNotGenerateAcw peers with native registrations as needing proxy/registration emission.
src/java-runtime/java-runtime.targetsDeletes obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts during build/clean.

Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Outdated
…emap
[JniAddNativeMethodRegistrationAttribute] is a legacy Java.Interop API whose
primary consumer — the jnimarshalmethod-gen build-time generator — was
removed in dotnet/java-interop#1405. The trimmable typemap deliberately does
not support this attribute.
When the scanner detects the attribute on any method, the generator emits
XA4251 telling the developer to either avoid it or switch off the trimmable
typemap (for example, by using the 'llvm-ir' type map implementation) and
report the scenario at https://github.com/dotnet/android/issues. The build
fails via TaskLoggingHelper.HasLoggedErrors.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival changed the title [TrimmableTypeMap] Use trimmable virtual-constructor fixtures[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251May 11, 2026
simonrozsivaland others added 3 commits May 11, 2026 12:05
Address review feedback:
- Drop JavaPeerInfo.HasJniAddNativeMethodRegistrationAttribute. The scanner
now takes an optional ITrimmableTypeMapLogger and reports XA4251 directly
when it encounters the attribute, instead of propagating a bool the rest
of the pipeline doesn't otherwise need.
- Drop the orchestrator's post-scan loop; TrimmableTypeMapGenerator just
passes its logger into JavaPeerScanner.
- Reset external/Java.Interop and external/xamarin-android-tools to the
SHAs on main; this PR doesn't need either submodule moved.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t/dot/jni/test/GetThis.java
This file is unrelated to the XA4251 work; it was accidentally removed during
an earlier 'git rm -r java-trimmable' cleanup. It's still needed by
JavaObjectTest.DisposeAccessesThis under the trimmable typemap.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The upstream Java.Interop test fixture CallVirtualFromConstructorDerived
uses [JniAddNativeMethodRegistrationAttribute]. Now that the trimmable
typemap refuses that attribute with XA4251, the offending sources need to
be excluded from the test assembly when building for the trimmable type
map; otherwise the build cannot reach the device tests at all.
Validated locally:
ANDROID_SERIAL=emulator-5554 MSBUILDDISABLENODEREUSE=1 \
./dotnet-local.sh build \
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj \
-t:RunTestApp -c Release \
-p:_AndroidTypeMapImplementation=trimmable \
-p:UseMonoRuntime=false -nr:false -m:1
TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total,
0 errors, 0 failures, 21 ignored.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Code-review caught that the prior placement of the XA4251 check sat *after*
the scanner's per-type filtering, so a type carrying the attribute but no
[Register] (and not extending a Java peer) would slip past the diagnostic
and the build would silently succeed.
Hoist the check to immediately after the <Module> skip so it fires uniformly
for every non-<Module> type, regardless of whether the type would otherwise
have been added to the typemap. Add a NonPeerNativeRegistration fixture to
the scanner test to guard the regression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 7ad46cf to 7d607c5CompareMay 11, 2026 10:53
…bute
Address Copilot reviewer feedback on the per-type method-attribute walk.
AssemblyIndex.Build now does a cheap pass over the TypeReferences and
TypeDefinitions tables to set MayUseJniAddNativeMethodRegistrationAttribute,
and the scanner short-circuits the per-method walk in the overwhelmingly
common case where the assembly neither imports nor declares the attribute.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
simonrozsival added a commit that referenced this pull request May 11, 2026
Squashed prerequisites from PR #11274 (trimmable-virtual-constructor):
reject [JniAddNativeMethodRegistrationAttribute] with XA4251 in the
trimmable typemap path and exclude the upstream
InvokeVirtualFromConstructor fixtures so the trimmable test assembly
builds.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 12, 2026
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Outdated
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Outdated
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Outdated
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot address reviewer's comments

CopilotAI commented May 13, 2026

Copy link
Copy Markdown
Contributor

@copilot address reviewer's comments

Addressed the reviewer feedback with namespace-aware matching in both the fast-check and per-method attribute match, plus regression coverage for same-name attributes in other namespaces. See commits d779cec and ed91def.

simonrozsivaland others added 2 commits May 13, 2026 14:24
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve merge conflicts: combine packageNamingPolicy and logger
parameters in JavaPeerScanner constructor.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jonathanpeppers
jonathanpeppers merged commit 61a5839 into mainMay 14, 2026
3 checks passed
@jonathanpeppers
jonathanpeppers deleted the trimmable-virtual-constructor branch May 14, 2026 20:53
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 14, 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 thisnice-to-haveready-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] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251 - #11274

Merged
jonathanpeppers merged 21 commits into
mainfrom
trimmable-virtual-constructor
May 14, 2026
Merged

[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251#11274
jonathanpeppers merged 21 commits into
mainfrom
trimmable-virtual-constructor

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented May 3, 2026

Copy link
Copy Markdown
Member

Refuses [JniAddNativeMethodRegistrationAttribute] in the trimmable typemap.

[JniAddNativeMethodRegistrationAttribute] is a legacy Java.Interop public API. Its primary consumer — the jnimarshalmethod-gen build-time generator that used to emit [JniAddNativeMethodRegistrationAttribute] static void __RegisterNativeMembers stubs on every JCW type — was removed in dotnet/java-interop#1405. The only remaining in-tree uses are Java.Interop's own JavaProxyObject / JavaProxyThrowable infrastructure types (already bypassed in the trimmable path by #11271) and a couple of upstream Java.Interop test fixtures. Supporting it in the trimmable typemap would mean adding scanner + ModelBuilder support for an obsolete code path with no in-tree consumers and a near-zero customer base.

This PR makes the design decision explicit:

  • JavaPeerScanner now takes an optional ITrimmableTypeMapLogger. When it encounters [JniAddNativeMethodRegistrationAttribute] on any method, it calls ITrimmableTypeMapLogger.LogJniAddNativeMethodRegistrationAttributeError directly from the per-type scan loop. No JavaPeerInfo property is propagated; the orchestrator simply passes its logger into new JavaPeerScanner(logger).
  • The MSBuild logger maps the call to XA4251, so GenerateTrimmableTypeMap fails the build via TaskLoggingHelper.HasLoggedErrors.
  • The message instructs developers to either avoid the attribute or switch off the trimmable typemap (for example, by using the llvm-ir type map implementation), and to report the scenario at https://github.com/dotnet/android/issues so the team can evaluate whether to support it.
  • Java.InteropTests.InvokeVirtualFromConstructorTests (which uses the attribute) is permanently excluded under the trimmable typemap with an explanatory comment pointing at this policy.
  • tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csproj excludes the upstream CallVirtualFromConstructor{Base,Derived}.cs and InvokeVirtualFromConstructorTests.cs from the test assembly compile when _AndroidTypeMapImplementation == trimmable, so the device-test build can compile through the trimmable typemap generator. (The other upstream user of the attribute, TestType.cs, is already gated by #if !NO_MARSHAL_MEMBER_BUILDER_SUPPORT, which the test csproj defines.)

Tests:

  • JavaPeerScannerTests.Scan_JniAddNativeMethodRegistrationAttribute_LogsError (new) gives the scanner a recording ITrimmableTypeMapLogger and asserts it logs XA4251 for HandWrittenNativeRegistrationPeer and not for unrelated fixture types.
  • TrimmableTypeMapGeneratorTests.Execute_WithJniAddNativeMethodRegistrationAttribute_ReportsXA4251 (new) verifies the orchestrator end-to-end emits XA4251 against the same fixture.

Device validation against an Android emulator with the CoreCLRTrimmable lane:

ANDROID_SERIAL=emulator-5554 MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build \
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj \
-t:RunTestApp -c Release \
-p:_AndroidTypeMapImplementation=trimmable -p:UseMonoRuntime=false \
-nr:false -m:1

TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total, 0 errors, 0 failures, 21 ignored.

Related issues

@simonrozsivalsimonrozsival changed the title Use trimmable virtual-constructor fixtures[TrimmableTypeMap] Use trimmable virtual-constructor fixturesMay 3, 2026
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 3, 2026
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from 1467afa to e66930eCompareMay 4, 2026 18:21
@simonrozsival
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 711aeae to 7e2737bCompareMay 4, 2026 18:23
simonrozsivaland others added 3 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>
Enable the Java.Interop virtual-constructor tests in the trimmable typemap lane by swapping in Android-owned Java fixtures that use Runtime.registerNatives and generated n_* callbacks instead of ManagedPeer.
Teach the trimmable typemap scanner/model to emit native registrations for hand-written Java peers that opt into JniAddNativeMethodRegistrationAttribute.
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
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 7e2737b to dc13b42CompareMay 4, 2026 18:31
simonrozsivaland others added 7 commits May 5, 2026 11:31
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>
…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
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>
Base automatically changed from trimmable-java-proxy-object to mainMay 11, 2026 07:16
…structor
# Conflicts:
#	src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs
#	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs
@simonrozsival
simonrozsival marked this pull request as ready for review May 11, 2026 09:11
CopilotAI review requested due to automatic review settings May 11, 2026 09:11
…mmableTypeMapBuildTests
This cleanup is not related to fixing InvokeVirtualFromConstructorTests
and belongs in a separate change.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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 re-enables Java.InteropTests.InvokeVirtualFromConstructorTests for the CoreCLR trimmable typemap lane by swapping desktop-JVM Java.Interop fixtures for Android/trimmable-compatible copies and extending the trimmable typemap generator to support native registrations for hand-written Java peers.

Changes:

  • Removes the trimmable-typemap exclusion for Java.InteropTests.InvokeVirtualFromConstructorTests and adds trimmable Java/C# fixtures for CallVirtualFromConstructor*.
  • Extends the trimmable typemap scanner/model to detect JniAddNativeMethodRegistrationAttribute usage and emit proxy/registration support accordingly.
  • Adds cleanup/validation for obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts (delete during build; assert not packaged in SDK tests).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.csRe-enables InvokeVirtualFromConstructorTests by removing its name-based exclusion.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-trimmable/CallVirtualFromConstructorDerived.csAdds trimmable managed peer fixture using generated n_* callbacks + JniAddNativeMethodRegistrationAttribute.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.targetsSwitches trimmable builds to include Android-owned Java fixtures in the test JAR and exclude the desktop versions.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csprojConditionally swaps the managed CallVirtualFromConstructorDerived source between desktop and trimmable variants.
tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorDerived.javaAdds Android/trimmable Java fixture using mono.android.Runtime.registerNatives(Class) via reflection.
tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorBase.javaAdds Android/trimmable base Java fixture using registerNatives(Class) via reflection.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.csVerifies obsolete net6/trimmable_clr runtime artifacts are not shipped in the SDK pack.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.csDetects method-level JniAddNativeMethodRegistrationAttribute to inform generation decisions.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerInfo.csStores whether a peer uses JniAddNativeMethodRegistrationAttribute.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.csTreats certain DoNotGenerateAcw peers with native registrations as needing proxy/registration emission.
src/java-runtime/java-runtime.targetsDeletes obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts during build/clean.

Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Outdated
…emap
[JniAddNativeMethodRegistrationAttribute] is a legacy Java.Interop API whose
primary consumer — the jnimarshalmethod-gen build-time generator — was
removed in dotnet/java-interop#1405. The trimmable typemap deliberately does
not support this attribute.
When the scanner detects the attribute on any method, the generator emits
XA4251 telling the developer to either avoid it or switch off the trimmable
typemap (for example, by using the 'llvm-ir' type map implementation) and
report the scenario at https://github.com/dotnet/android/issues. The build
fails via TaskLoggingHelper.HasLoggedErrors.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival changed the title [TrimmableTypeMap] Use trimmable virtual-constructor fixtures[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251May 11, 2026
simonrozsivaland others added 3 commits May 11, 2026 12:05
Address review feedback:
- Drop JavaPeerInfo.HasJniAddNativeMethodRegistrationAttribute. The scanner
now takes an optional ITrimmableTypeMapLogger and reports XA4251 directly
when it encounters the attribute, instead of propagating a bool the rest
of the pipeline doesn't otherwise need.
- Drop the orchestrator's post-scan loop; TrimmableTypeMapGenerator just
passes its logger into JavaPeerScanner.
- Reset external/Java.Interop and external/xamarin-android-tools to the
SHAs on main; this PR doesn't need either submodule moved.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t/dot/jni/test/GetThis.java
This file is unrelated to the XA4251 work; it was accidentally removed during
an earlier 'git rm -r java-trimmable' cleanup. It's still needed by
JavaObjectTest.DisposeAccessesThis under the trimmable typemap.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The upstream Java.Interop test fixture CallVirtualFromConstructorDerived
uses [JniAddNativeMethodRegistrationAttribute]. Now that the trimmable
typemap refuses that attribute with XA4251, the offending sources need to
be excluded from the test assembly when building for the trimmable type
map; otherwise the build cannot reach the device tests at all.
Validated locally:
ANDROID_SERIAL=emulator-5554 MSBUILDDISABLENODEREUSE=1 \
./dotnet-local.sh build \
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj \
-t:RunTestApp -c Release \
-p:_AndroidTypeMapImplementation=trimmable \
-p:UseMonoRuntime=false -nr:false -m:1
TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total,
0 errors, 0 failures, 21 ignored.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Code-review caught that the prior placement of the XA4251 check sat *after*
the scanner's per-type filtering, so a type carrying the attribute but no
[Register] (and not extending a Java peer) would slip past the diagnostic
and the build would silently succeed.
Hoist the check to immediately after the <Module> skip so it fires uniformly
for every non-<Module> type, regardless of whether the type would otherwise
have been added to the typemap. Add a NonPeerNativeRegistration fixture to
the scanner test to guard the regression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 7ad46cf to 7d607c5CompareMay 11, 2026 10:53
…bute
Address Copilot reviewer feedback on the per-type method-attribute walk.
AssemblyIndex.Build now does a cheap pass over the TypeReferences and
TypeDefinitions tables to set MayUseJniAddNativeMethodRegistrationAttribute,
and the scanner short-circuits the per-method walk in the overwhelmingly
common case where the assembly neither imports nor declares the attribute.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
simonrozsival added a commit that referenced this pull request May 11, 2026
Squashed prerequisites from PR #11274 (trimmable-virtual-constructor):
reject [JniAddNativeMethodRegistrationAttribute] with XA4251 in the
trimmable typemap path and exclude the upstream
InvokeVirtualFromConstructor fixtures so the trimmable test assembly
builds.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 12, 2026
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Outdated
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Outdated
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Outdated
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot address reviewer's comments

CopilotAI commented May 13, 2026

Copy link
Copy Markdown
Contributor

@copilot address reviewer's comments

Addressed the reviewer feedback with namespace-aware matching in both the fast-check and per-method attribute match, plus regression coverage for same-name attributes in other namespaces. See commits d779cec and ed91def.

simonrozsivaland others added 2 commits May 13, 2026 14:24
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve merge conflicts: combine packageNamingPolicy and logger
parameters in JavaPeerScanner constructor.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jonathanpeppers
jonathanpeppers merged commit 61a5839 into mainMay 14, 2026
3 checks passed
@jonathanpeppers
jonathanpeppers deleted the trimmable-virtual-constructor branch May 14, 2026 20:53
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 14, 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 thisnice-to-haveready-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] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251 - #11274

Merged
jonathanpeppers merged 21 commits into
mainfrom
trimmable-virtual-constructor
May 14, 2026
Merged

[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251#11274
jonathanpeppers merged 21 commits into
mainfrom
trimmable-virtual-constructor

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented May 3, 2026

Copy link
Copy Markdown
Member

Refuses [JniAddNativeMethodRegistrationAttribute] in the trimmable typemap.

[JniAddNativeMethodRegistrationAttribute] is a legacy Java.Interop public API. Its primary consumer — the jnimarshalmethod-gen build-time generator that used to emit [JniAddNativeMethodRegistrationAttribute] static void __RegisterNativeMembers stubs on every JCW type — was removed in dotnet/java-interop#1405. The only remaining in-tree uses are Java.Interop's own JavaProxyObject / JavaProxyThrowable infrastructure types (already bypassed in the trimmable path by #11271) and a couple of upstream Java.Interop test fixtures. Supporting it in the trimmable typemap would mean adding scanner + ModelBuilder support for an obsolete code path with no in-tree consumers and a near-zero customer base.

This PR makes the design decision explicit:

  • JavaPeerScanner now takes an optional ITrimmableTypeMapLogger. When it encounters [JniAddNativeMethodRegistrationAttribute] on any method, it calls ITrimmableTypeMapLogger.LogJniAddNativeMethodRegistrationAttributeError directly from the per-type scan loop. No JavaPeerInfo property is propagated; the orchestrator simply passes its logger into new JavaPeerScanner(logger).
  • The MSBuild logger maps the call to XA4251, so GenerateTrimmableTypeMap fails the build via TaskLoggingHelper.HasLoggedErrors.
  • The message instructs developers to either avoid the attribute or switch off the trimmable typemap (for example, by using the llvm-ir type map implementation), and to report the scenario at https://github.com/dotnet/android/issues so the team can evaluate whether to support it.
  • Java.InteropTests.InvokeVirtualFromConstructorTests (which uses the attribute) is permanently excluded under the trimmable typemap with an explanatory comment pointing at this policy.
  • tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csproj excludes the upstream CallVirtualFromConstructor{Base,Derived}.cs and InvokeVirtualFromConstructorTests.cs from the test assembly compile when _AndroidTypeMapImplementation == trimmable, so the device-test build can compile through the trimmable typemap generator. (The other upstream user of the attribute, TestType.cs, is already gated by #if !NO_MARSHAL_MEMBER_BUILDER_SUPPORT, which the test csproj defines.)

Tests:

  • JavaPeerScannerTests.Scan_JniAddNativeMethodRegistrationAttribute_LogsError (new) gives the scanner a recording ITrimmableTypeMapLogger and asserts it logs XA4251 for HandWrittenNativeRegistrationPeer and not for unrelated fixture types.
  • TrimmableTypeMapGeneratorTests.Execute_WithJniAddNativeMethodRegistrationAttribute_ReportsXA4251 (new) verifies the orchestrator end-to-end emits XA4251 against the same fixture.

Device validation against an Android emulator with the CoreCLRTrimmable lane:

ANDROID_SERIAL=emulator-5554 MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build \
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj \
-t:RunTestApp -c Release \
-p:_AndroidTypeMapImplementation=trimmable -p:UseMonoRuntime=false \
-nr:false -m:1

TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total, 0 errors, 0 failures, 21 ignored.

Related issues

@simonrozsivalsimonrozsival changed the title Use trimmable virtual-constructor fixtures[TrimmableTypeMap] Use trimmable virtual-constructor fixturesMay 3, 2026
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 3, 2026
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from 1467afa to e66930eCompareMay 4, 2026 18:21
@simonrozsival
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 711aeae to 7e2737bCompareMay 4, 2026 18:23
simonrozsivaland others added 3 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>
Enable the Java.Interop virtual-constructor tests in the trimmable typemap lane by swapping in Android-owned Java fixtures that use Runtime.registerNatives and generated n_* callbacks instead of ManagedPeer.
Teach the trimmable typemap scanner/model to emit native registrations for hand-written Java peers that opt into JniAddNativeMethodRegistrationAttribute.
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
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 7e2737b to dc13b42CompareMay 4, 2026 18:31
simonrozsivaland others added 7 commits May 5, 2026 11:31
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>
…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
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>
Base automatically changed from trimmable-java-proxy-object to mainMay 11, 2026 07:16
…structor
# Conflicts:
#	src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs
#	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs
@simonrozsival
simonrozsival marked this pull request as ready for review May 11, 2026 09:11
CopilotAI review requested due to automatic review settings May 11, 2026 09:11
…mmableTypeMapBuildTests
This cleanup is not related to fixing InvokeVirtualFromConstructorTests
and belongs in a separate change.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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 re-enables Java.InteropTests.InvokeVirtualFromConstructorTests for the CoreCLR trimmable typemap lane by swapping desktop-JVM Java.Interop fixtures for Android/trimmable-compatible copies and extending the trimmable typemap generator to support native registrations for hand-written Java peers.

Changes:

  • Removes the trimmable-typemap exclusion for Java.InteropTests.InvokeVirtualFromConstructorTests and adds trimmable Java/C# fixtures for CallVirtualFromConstructor*.
  • Extends the trimmable typemap scanner/model to detect JniAddNativeMethodRegistrationAttribute usage and emit proxy/registration support accordingly.
  • Adds cleanup/validation for obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts (delete during build; assert not packaged in SDK tests).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.csRe-enables InvokeVirtualFromConstructorTests by removing its name-based exclusion.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-trimmable/CallVirtualFromConstructorDerived.csAdds trimmable managed peer fixture using generated n_* callbacks + JniAddNativeMethodRegistrationAttribute.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.targetsSwitches trimmable builds to include Android-owned Java fixtures in the test JAR and exclude the desktop versions.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csprojConditionally swaps the managed CallVirtualFromConstructorDerived source between desktop and trimmable variants.
tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorDerived.javaAdds Android/trimmable Java fixture using mono.android.Runtime.registerNatives(Class) via reflection.
tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorBase.javaAdds Android/trimmable base Java fixture using registerNatives(Class) via reflection.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.csVerifies obsolete net6/trimmable_clr runtime artifacts are not shipped in the SDK pack.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.csDetects method-level JniAddNativeMethodRegistrationAttribute to inform generation decisions.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerInfo.csStores whether a peer uses JniAddNativeMethodRegistrationAttribute.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.csTreats certain DoNotGenerateAcw peers with native registrations as needing proxy/registration emission.
src/java-runtime/java-runtime.targetsDeletes obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts during build/clean.

Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Outdated
…emap
[JniAddNativeMethodRegistrationAttribute] is a legacy Java.Interop API whose
primary consumer — the jnimarshalmethod-gen build-time generator — was
removed in dotnet/java-interop#1405. The trimmable typemap deliberately does
not support this attribute.
When the scanner detects the attribute on any method, the generator emits
XA4251 telling the developer to either avoid it or switch off the trimmable
typemap (for example, by using the 'llvm-ir' type map implementation) and
report the scenario at https://github.com/dotnet/android/issues. The build
fails via TaskLoggingHelper.HasLoggedErrors.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival changed the title [TrimmableTypeMap] Use trimmable virtual-constructor fixtures[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251May 11, 2026
simonrozsivaland others added 3 commits May 11, 2026 12:05
Address review feedback:
- Drop JavaPeerInfo.HasJniAddNativeMethodRegistrationAttribute. The scanner
now takes an optional ITrimmableTypeMapLogger and reports XA4251 directly
when it encounters the attribute, instead of propagating a bool the rest
of the pipeline doesn't otherwise need.
- Drop the orchestrator's post-scan loop; TrimmableTypeMapGenerator just
passes its logger into JavaPeerScanner.
- Reset external/Java.Interop and external/xamarin-android-tools to the
SHAs on main; this PR doesn't need either submodule moved.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t/dot/jni/test/GetThis.java
This file is unrelated to the XA4251 work; it was accidentally removed during
an earlier 'git rm -r java-trimmable' cleanup. It's still needed by
JavaObjectTest.DisposeAccessesThis under the trimmable typemap.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The upstream Java.Interop test fixture CallVirtualFromConstructorDerived
uses [JniAddNativeMethodRegistrationAttribute]. Now that the trimmable
typemap refuses that attribute with XA4251, the offending sources need to
be excluded from the test assembly when building for the trimmable type
map; otherwise the build cannot reach the device tests at all.
Validated locally:
ANDROID_SERIAL=emulator-5554 MSBUILDDISABLENODEREUSE=1 \
./dotnet-local.sh build \
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj \
-t:RunTestApp -c Release \
-p:_AndroidTypeMapImplementation=trimmable \
-p:UseMonoRuntime=false -nr:false -m:1
TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total,
0 errors, 0 failures, 21 ignored.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Code-review caught that the prior placement of the XA4251 check sat *after*
the scanner's per-type filtering, so a type carrying the attribute but no
[Register] (and not extending a Java peer) would slip past the diagnostic
and the build would silently succeed.
Hoist the check to immediately after the <Module> skip so it fires uniformly
for every non-<Module> type, regardless of whether the type would otherwise
have been added to the typemap. Add a NonPeerNativeRegistration fixture to
the scanner test to guard the regression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 7ad46cf to 7d607c5CompareMay 11, 2026 10:53
…bute
Address Copilot reviewer feedback on the per-type method-attribute walk.
AssemblyIndex.Build now does a cheap pass over the TypeReferences and
TypeDefinitions tables to set MayUseJniAddNativeMethodRegistrationAttribute,
and the scanner short-circuits the per-method walk in the overwhelmingly
common case where the assembly neither imports nor declares the attribute.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
simonrozsival added a commit that referenced this pull request May 11, 2026
Squashed prerequisites from PR #11274 (trimmable-virtual-constructor):
reject [JniAddNativeMethodRegistrationAttribute] with XA4251 in the
trimmable typemap path and exclude the upstream
InvokeVirtualFromConstructor fixtures so the trimmable test assembly
builds.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 12, 2026
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Outdated
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Outdated
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Outdated
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot address reviewer's comments

CopilotAI commented May 13, 2026

Copy link
Copy Markdown
Contributor

@copilot address reviewer's comments

Addressed the reviewer feedback with namespace-aware matching in both the fast-check and per-method attribute match, plus regression coverage for same-name attributes in other namespaces. See commits d779cec and ed91def.

simonrozsivaland others added 2 commits May 13, 2026 14:24
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve merge conflicts: combine packageNamingPolicy and logger
parameters in JavaPeerScanner constructor.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jonathanpeppers
jonathanpeppers merged commit 61a5839 into mainMay 14, 2026
3 checks passed
@jonathanpeppers
jonathanpeppers deleted the trimmable-virtual-constructor branch May 14, 2026 20:53
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 14, 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 thisnice-to-haveready-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] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251 - #11274

Merged
jonathanpeppers merged 21 commits into
mainfrom
trimmable-virtual-constructor
May 14, 2026
Merged

[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251#11274
jonathanpeppers merged 21 commits into
mainfrom
trimmable-virtual-constructor

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented May 3, 2026

Copy link
Copy Markdown
Member

Refuses [JniAddNativeMethodRegistrationAttribute] in the trimmable typemap.

[JniAddNativeMethodRegistrationAttribute] is a legacy Java.Interop public API. Its primary consumer — the jnimarshalmethod-gen build-time generator that used to emit [JniAddNativeMethodRegistrationAttribute] static void __RegisterNativeMembers stubs on every JCW type — was removed in dotnet/java-interop#1405. The only remaining in-tree uses are Java.Interop's own JavaProxyObject / JavaProxyThrowable infrastructure types (already bypassed in the trimmable path by #11271) and a couple of upstream Java.Interop test fixtures. Supporting it in the trimmable typemap would mean adding scanner + ModelBuilder support for an obsolete code path with no in-tree consumers and a near-zero customer base.

This PR makes the design decision explicit:

  • JavaPeerScanner now takes an optional ITrimmableTypeMapLogger. When it encounters [JniAddNativeMethodRegistrationAttribute] on any method, it calls ITrimmableTypeMapLogger.LogJniAddNativeMethodRegistrationAttributeError directly from the per-type scan loop. No JavaPeerInfo property is propagated; the orchestrator simply passes its logger into new JavaPeerScanner(logger).
  • The MSBuild logger maps the call to XA4251, so GenerateTrimmableTypeMap fails the build via TaskLoggingHelper.HasLoggedErrors.
  • The message instructs developers to either avoid the attribute or switch off the trimmable typemap (for example, by using the llvm-ir type map implementation), and to report the scenario at https://github.com/dotnet/android/issues so the team can evaluate whether to support it.
  • Java.InteropTests.InvokeVirtualFromConstructorTests (which uses the attribute) is permanently excluded under the trimmable typemap with an explanatory comment pointing at this policy.
  • tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csproj excludes the upstream CallVirtualFromConstructor{Base,Derived}.cs and InvokeVirtualFromConstructorTests.cs from the test assembly compile when _AndroidTypeMapImplementation == trimmable, so the device-test build can compile through the trimmable typemap generator. (The other upstream user of the attribute, TestType.cs, is already gated by #if !NO_MARSHAL_MEMBER_BUILDER_SUPPORT, which the test csproj defines.)

Tests:

  • JavaPeerScannerTests.Scan_JniAddNativeMethodRegistrationAttribute_LogsError (new) gives the scanner a recording ITrimmableTypeMapLogger and asserts it logs XA4251 for HandWrittenNativeRegistrationPeer and not for unrelated fixture types.
  • TrimmableTypeMapGeneratorTests.Execute_WithJniAddNativeMethodRegistrationAttribute_ReportsXA4251 (new) verifies the orchestrator end-to-end emits XA4251 against the same fixture.

Device validation against an Android emulator with the CoreCLRTrimmable lane:

ANDROID_SERIAL=emulator-5554 MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build \
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj \
-t:RunTestApp -c Release \
-p:_AndroidTypeMapImplementation=trimmable -p:UseMonoRuntime=false \
-nr:false -m:1

TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total, 0 errors, 0 failures, 21 ignored.

Related issues

@simonrozsivalsimonrozsival changed the title Use trimmable virtual-constructor fixtures[TrimmableTypeMap] Use trimmable virtual-constructor fixturesMay 3, 2026
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 3, 2026
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from 1467afa to e66930eCompareMay 4, 2026 18:21
@simonrozsival
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 711aeae to 7e2737bCompareMay 4, 2026 18:23
simonrozsivaland others added 3 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>
Enable the Java.Interop virtual-constructor tests in the trimmable typemap lane by swapping in Android-owned Java fixtures that use Runtime.registerNatives and generated n_* callbacks instead of ManagedPeer.
Teach the trimmable typemap scanner/model to emit native registrations for hand-written Java peers that opt into JniAddNativeMethodRegistrationAttribute.
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
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 7e2737b to dc13b42CompareMay 4, 2026 18:31
simonrozsivaland others added 7 commits May 5, 2026 11:31
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>
…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
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>
Base automatically changed from trimmable-java-proxy-object to mainMay 11, 2026 07:16
…structor
# Conflicts:
#	src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs
#	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs
@simonrozsival
simonrozsival marked this pull request as ready for review May 11, 2026 09:11
CopilotAI review requested due to automatic review settings May 11, 2026 09:11
…mmableTypeMapBuildTests
This cleanup is not related to fixing InvokeVirtualFromConstructorTests
and belongs in a separate change.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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 re-enables Java.InteropTests.InvokeVirtualFromConstructorTests for the CoreCLR trimmable typemap lane by swapping desktop-JVM Java.Interop fixtures for Android/trimmable-compatible copies and extending the trimmable typemap generator to support native registrations for hand-written Java peers.

Changes:

  • Removes the trimmable-typemap exclusion for Java.InteropTests.InvokeVirtualFromConstructorTests and adds trimmable Java/C# fixtures for CallVirtualFromConstructor*.
  • Extends the trimmable typemap scanner/model to detect JniAddNativeMethodRegistrationAttribute usage and emit proxy/registration support accordingly.
  • Adds cleanup/validation for obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts (delete during build; assert not packaged in SDK tests).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.csRe-enables InvokeVirtualFromConstructorTests by removing its name-based exclusion.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-trimmable/CallVirtualFromConstructorDerived.csAdds trimmable managed peer fixture using generated n_* callbacks + JniAddNativeMethodRegistrationAttribute.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.targetsSwitches trimmable builds to include Android-owned Java fixtures in the test JAR and exclude the desktop versions.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csprojConditionally swaps the managed CallVirtualFromConstructorDerived source between desktop and trimmable variants.
tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorDerived.javaAdds Android/trimmable Java fixture using mono.android.Runtime.registerNatives(Class) via reflection.
tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorBase.javaAdds Android/trimmable base Java fixture using registerNatives(Class) via reflection.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.csVerifies obsolete net6/trimmable_clr runtime artifacts are not shipped in the SDK pack.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.csDetects method-level JniAddNativeMethodRegistrationAttribute to inform generation decisions.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerInfo.csStores whether a peer uses JniAddNativeMethodRegistrationAttribute.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.csTreats certain DoNotGenerateAcw peers with native registrations as needing proxy/registration emission.
src/java-runtime/java-runtime.targetsDeletes obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts during build/clean.

Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Outdated
…emap
[JniAddNativeMethodRegistrationAttribute] is a legacy Java.Interop API whose
primary consumer — the jnimarshalmethod-gen build-time generator — was
removed in dotnet/java-interop#1405. The trimmable typemap deliberately does
not support this attribute.
When the scanner detects the attribute on any method, the generator emits
XA4251 telling the developer to either avoid it or switch off the trimmable
typemap (for example, by using the 'llvm-ir' type map implementation) and
report the scenario at https://github.com/dotnet/android/issues. The build
fails via TaskLoggingHelper.HasLoggedErrors.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival changed the title [TrimmableTypeMap] Use trimmable virtual-constructor fixtures[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251May 11, 2026
simonrozsivaland others added 3 commits May 11, 2026 12:05
Address review feedback:
- Drop JavaPeerInfo.HasJniAddNativeMethodRegistrationAttribute. The scanner
now takes an optional ITrimmableTypeMapLogger and reports XA4251 directly
when it encounters the attribute, instead of propagating a bool the rest
of the pipeline doesn't otherwise need.
- Drop the orchestrator's post-scan loop; TrimmableTypeMapGenerator just
passes its logger into JavaPeerScanner.
- Reset external/Java.Interop and external/xamarin-android-tools to the
SHAs on main; this PR doesn't need either submodule moved.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t/dot/jni/test/GetThis.java
This file is unrelated to the XA4251 work; it was accidentally removed during
an earlier 'git rm -r java-trimmable' cleanup. It's still needed by
JavaObjectTest.DisposeAccessesThis under the trimmable typemap.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The upstream Java.Interop test fixture CallVirtualFromConstructorDerived
uses [JniAddNativeMethodRegistrationAttribute]. Now that the trimmable
typemap refuses that attribute with XA4251, the offending sources need to
be excluded from the test assembly when building for the trimmable type
map; otherwise the build cannot reach the device tests at all.
Validated locally:
ANDROID_SERIAL=emulator-5554 MSBUILDDISABLENODEREUSE=1 \
./dotnet-local.sh build \
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj \
-t:RunTestApp -c Release \
-p:_AndroidTypeMapImplementation=trimmable \
-p:UseMonoRuntime=false -nr:false -m:1
TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total,
0 errors, 0 failures, 21 ignored.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Code-review caught that the prior placement of the XA4251 check sat *after*
the scanner's per-type filtering, so a type carrying the attribute but no
[Register] (and not extending a Java peer) would slip past the diagnostic
and the build would silently succeed.
Hoist the check to immediately after the <Module> skip so it fires uniformly
for every non-<Module> type, regardless of whether the type would otherwise
have been added to the typemap. Add a NonPeerNativeRegistration fixture to
the scanner test to guard the regression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 7ad46cf to 7d607c5CompareMay 11, 2026 10:53
…bute
Address Copilot reviewer feedback on the per-type method-attribute walk.
AssemblyIndex.Build now does a cheap pass over the TypeReferences and
TypeDefinitions tables to set MayUseJniAddNativeMethodRegistrationAttribute,
and the scanner short-circuits the per-method walk in the overwhelmingly
common case where the assembly neither imports nor declares the attribute.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
simonrozsival added a commit that referenced this pull request May 11, 2026
Squashed prerequisites from PR #11274 (trimmable-virtual-constructor):
reject [JniAddNativeMethodRegistrationAttribute] with XA4251 in the
trimmable typemap path and exclude the upstream
InvokeVirtualFromConstructor fixtures so the trimmable test assembly
builds.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 12, 2026
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Outdated
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Outdated
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Outdated
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot address reviewer's comments

CopilotAI commented May 13, 2026

Copy link
Copy Markdown
Contributor

@copilot address reviewer's comments

Addressed the reviewer feedback with namespace-aware matching in both the fast-check and per-method attribute match, plus regression coverage for same-name attributes in other namespaces. See commits d779cec and ed91def.

simonrozsivaland others added 2 commits May 13, 2026 14:24
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve merge conflicts: combine packageNamingPolicy and logger
parameters in JavaPeerScanner constructor.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jonathanpeppers
jonathanpeppers merged commit 61a5839 into mainMay 14, 2026
3 checks passed
@jonathanpeppers
jonathanpeppers deleted the trimmable-virtual-constructor branch May 14, 2026 20:53
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 14, 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 thisnice-to-haveready-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] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251 - #11274

Merged
jonathanpeppers merged 21 commits into
mainfrom
trimmable-virtual-constructor
May 14, 2026
Merged

[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251#11274
jonathanpeppers merged 21 commits into
mainfrom
trimmable-virtual-constructor

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented May 3, 2026

Copy link
Copy Markdown
Member

Refuses [JniAddNativeMethodRegistrationAttribute] in the trimmable typemap.

[JniAddNativeMethodRegistrationAttribute] is a legacy Java.Interop public API. Its primary consumer — the jnimarshalmethod-gen build-time generator that used to emit [JniAddNativeMethodRegistrationAttribute] static void __RegisterNativeMembers stubs on every JCW type — was removed in dotnet/java-interop#1405. The only remaining in-tree uses are Java.Interop's own JavaProxyObject / JavaProxyThrowable infrastructure types (already bypassed in the trimmable path by #11271) and a couple of upstream Java.Interop test fixtures. Supporting it in the trimmable typemap would mean adding scanner + ModelBuilder support for an obsolete code path with no in-tree consumers and a near-zero customer base.

This PR makes the design decision explicit:

  • JavaPeerScanner now takes an optional ITrimmableTypeMapLogger. When it encounters [JniAddNativeMethodRegistrationAttribute] on any method, it calls ITrimmableTypeMapLogger.LogJniAddNativeMethodRegistrationAttributeError directly from the per-type scan loop. No JavaPeerInfo property is propagated; the orchestrator simply passes its logger into new JavaPeerScanner(logger).
  • The MSBuild logger maps the call to XA4251, so GenerateTrimmableTypeMap fails the build via TaskLoggingHelper.HasLoggedErrors.
  • The message instructs developers to either avoid the attribute or switch off the trimmable typemap (for example, by using the llvm-ir type map implementation), and to report the scenario at https://github.com/dotnet/android/issues so the team can evaluate whether to support it.
  • Java.InteropTests.InvokeVirtualFromConstructorTests (which uses the attribute) is permanently excluded under the trimmable typemap with an explanatory comment pointing at this policy.
  • tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csproj excludes the upstream CallVirtualFromConstructor{Base,Derived}.cs and InvokeVirtualFromConstructorTests.cs from the test assembly compile when _AndroidTypeMapImplementation == trimmable, so the device-test build can compile through the trimmable typemap generator. (The other upstream user of the attribute, TestType.cs, is already gated by #if !NO_MARSHAL_MEMBER_BUILDER_SUPPORT, which the test csproj defines.)

Tests:

  • JavaPeerScannerTests.Scan_JniAddNativeMethodRegistrationAttribute_LogsError (new) gives the scanner a recording ITrimmableTypeMapLogger and asserts it logs XA4251 for HandWrittenNativeRegistrationPeer and not for unrelated fixture types.
  • TrimmableTypeMapGeneratorTests.Execute_WithJniAddNativeMethodRegistrationAttribute_ReportsXA4251 (new) verifies the orchestrator end-to-end emits XA4251 against the same fixture.

Device validation against an Android emulator with the CoreCLRTrimmable lane:

ANDROID_SERIAL=emulator-5554 MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build \
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj \
-t:RunTestApp -c Release \
-p:_AndroidTypeMapImplementation=trimmable -p:UseMonoRuntime=false \
-nr:false -m:1

TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total, 0 errors, 0 failures, 21 ignored.

Related issues

@simonrozsivalsimonrozsival changed the title Use trimmable virtual-constructor fixtures[TrimmableTypeMap] Use trimmable virtual-constructor fixturesMay 3, 2026
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 3, 2026
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from 1467afa to e66930eCompareMay 4, 2026 18:21
@simonrozsival
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 711aeae to 7e2737bCompareMay 4, 2026 18:23
simonrozsivaland others added 3 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>
Enable the Java.Interop virtual-constructor tests in the trimmable typemap lane by swapping in Android-owned Java fixtures that use Runtime.registerNatives and generated n_* callbacks instead of ManagedPeer.
Teach the trimmable typemap scanner/model to emit native registrations for hand-written Java peers that opt into JniAddNativeMethodRegistrationAttribute.
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
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 7e2737b to dc13b42CompareMay 4, 2026 18:31
simonrozsivaland others added 7 commits May 5, 2026 11:31
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>
…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
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>
Base automatically changed from trimmable-java-proxy-object to mainMay 11, 2026 07:16
…structor
# Conflicts:
#	src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs
#	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs
@simonrozsival
simonrozsival marked this pull request as ready for review May 11, 2026 09:11
CopilotAI review requested due to automatic review settings May 11, 2026 09:11
…mmableTypeMapBuildTests
This cleanup is not related to fixing InvokeVirtualFromConstructorTests
and belongs in a separate change.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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 re-enables Java.InteropTests.InvokeVirtualFromConstructorTests for the CoreCLR trimmable typemap lane by swapping desktop-JVM Java.Interop fixtures for Android/trimmable-compatible copies and extending the trimmable typemap generator to support native registrations for hand-written Java peers.

Changes:

  • Removes the trimmable-typemap exclusion for Java.InteropTests.InvokeVirtualFromConstructorTests and adds trimmable Java/C# fixtures for CallVirtualFromConstructor*.
  • Extends the trimmable typemap scanner/model to detect JniAddNativeMethodRegistrationAttribute usage and emit proxy/registration support accordingly.
  • Adds cleanup/validation for obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts (delete during build; assert not packaged in SDK tests).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.csRe-enables InvokeVirtualFromConstructorTests by removing its name-based exclusion.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-trimmable/CallVirtualFromConstructorDerived.csAdds trimmable managed peer fixture using generated n_* callbacks + JniAddNativeMethodRegistrationAttribute.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.targetsSwitches trimmable builds to include Android-owned Java fixtures in the test JAR and exclude the desktop versions.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csprojConditionally swaps the managed CallVirtualFromConstructorDerived source between desktop and trimmable variants.
tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorDerived.javaAdds Android/trimmable Java fixture using mono.android.Runtime.registerNatives(Class) via reflection.
tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorBase.javaAdds Android/trimmable base Java fixture using registerNatives(Class) via reflection.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.csVerifies obsolete net6/trimmable_clr runtime artifacts are not shipped in the SDK pack.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.csDetects method-level JniAddNativeMethodRegistrationAttribute to inform generation decisions.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerInfo.csStores whether a peer uses JniAddNativeMethodRegistrationAttribute.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.csTreats certain DoNotGenerateAcw peers with native registrations as needing proxy/registration emission.
src/java-runtime/java-runtime.targetsDeletes obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts during build/clean.

Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Outdated
…emap
[JniAddNativeMethodRegistrationAttribute] is a legacy Java.Interop API whose
primary consumer — the jnimarshalmethod-gen build-time generator — was
removed in dotnet/java-interop#1405. The trimmable typemap deliberately does
not support this attribute.
When the scanner detects the attribute on any method, the generator emits
XA4251 telling the developer to either avoid it or switch off the trimmable
typemap (for example, by using the 'llvm-ir' type map implementation) and
report the scenario at https://github.com/dotnet/android/issues. The build
fails via TaskLoggingHelper.HasLoggedErrors.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival changed the title [TrimmableTypeMap] Use trimmable virtual-constructor fixtures[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251May 11, 2026
simonrozsivaland others added 3 commits May 11, 2026 12:05
Address review feedback:
- Drop JavaPeerInfo.HasJniAddNativeMethodRegistrationAttribute. The scanner
now takes an optional ITrimmableTypeMapLogger and reports XA4251 directly
when it encounters the attribute, instead of propagating a bool the rest
of the pipeline doesn't otherwise need.
- Drop the orchestrator's post-scan loop; TrimmableTypeMapGenerator just
passes its logger into JavaPeerScanner.
- Reset external/Java.Interop and external/xamarin-android-tools to the
SHAs on main; this PR doesn't need either submodule moved.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t/dot/jni/test/GetThis.java
This file is unrelated to the XA4251 work; it was accidentally removed during
an earlier 'git rm -r java-trimmable' cleanup. It's still needed by
JavaObjectTest.DisposeAccessesThis under the trimmable typemap.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The upstream Java.Interop test fixture CallVirtualFromConstructorDerived
uses [JniAddNativeMethodRegistrationAttribute]. Now that the trimmable
typemap refuses that attribute with XA4251, the offending sources need to
be excluded from the test assembly when building for the trimmable type
map; otherwise the build cannot reach the device tests at all.
Validated locally:
ANDROID_SERIAL=emulator-5554 MSBUILDDISABLENODEREUSE=1 \
./dotnet-local.sh build \
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj \
-t:RunTestApp -c Release \
-p:_AndroidTypeMapImplementation=trimmable \
-p:UseMonoRuntime=false -nr:false -m:1
TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total,
0 errors, 0 failures, 21 ignored.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Code-review caught that the prior placement of the XA4251 check sat *after*
the scanner's per-type filtering, so a type carrying the attribute but no
[Register] (and not extending a Java peer) would slip past the diagnostic
and the build would silently succeed.
Hoist the check to immediately after the <Module> skip so it fires uniformly
for every non-<Module> type, regardless of whether the type would otherwise
have been added to the typemap. Add a NonPeerNativeRegistration fixture to
the scanner test to guard the regression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 7ad46cf to 7d607c5CompareMay 11, 2026 10:53
…bute
Address Copilot reviewer feedback on the per-type method-attribute walk.
AssemblyIndex.Build now does a cheap pass over the TypeReferences and
TypeDefinitions tables to set MayUseJniAddNativeMethodRegistrationAttribute,
and the scanner short-circuits the per-method walk in the overwhelmingly
common case where the assembly neither imports nor declares the attribute.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
simonrozsival added a commit that referenced this pull request May 11, 2026
Squashed prerequisites from PR #11274 (trimmable-virtual-constructor):
reject [JniAddNativeMethodRegistrationAttribute] with XA4251 in the
trimmable typemap path and exclude the upstream
InvokeVirtualFromConstructor fixtures so the trimmable test assembly
builds.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 12, 2026
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Outdated
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Outdated
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Outdated
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot address reviewer's comments

CopilotAI commented May 13, 2026

Copy link
Copy Markdown
Contributor

@copilot address reviewer's comments

Addressed the reviewer feedback with namespace-aware matching in both the fast-check and per-method attribute match, plus regression coverage for same-name attributes in other namespaces. See commits d779cec and ed91def.

simonrozsivaland others added 2 commits May 13, 2026 14:24
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve merge conflicts: combine packageNamingPolicy and logger
parameters in JavaPeerScanner constructor.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jonathanpeppers
jonathanpeppers merged commit 61a5839 into mainMay 14, 2026
3 checks passed
@jonathanpeppers
jonathanpeppers deleted the trimmable-virtual-constructor branch May 14, 2026 20:53
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 14, 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 thisnice-to-haveready-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] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251 - #11274

Merged
jonathanpeppers merged 21 commits into
mainfrom
trimmable-virtual-constructor
May 14, 2026
Merged

[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251#11274
jonathanpeppers merged 21 commits into
mainfrom
trimmable-virtual-constructor

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented May 3, 2026

Copy link
Copy Markdown
Member

Refuses [JniAddNativeMethodRegistrationAttribute] in the trimmable typemap.

[JniAddNativeMethodRegistrationAttribute] is a legacy Java.Interop public API. Its primary consumer — the jnimarshalmethod-gen build-time generator that used to emit [JniAddNativeMethodRegistrationAttribute] static void __RegisterNativeMembers stubs on every JCW type — was removed in dotnet/java-interop#1405. The only remaining in-tree uses are Java.Interop's own JavaProxyObject / JavaProxyThrowable infrastructure types (already bypassed in the trimmable path by #11271) and a couple of upstream Java.Interop test fixtures. Supporting it in the trimmable typemap would mean adding scanner + ModelBuilder support for an obsolete code path with no in-tree consumers and a near-zero customer base.

This PR makes the design decision explicit:

  • JavaPeerScanner now takes an optional ITrimmableTypeMapLogger. When it encounters [JniAddNativeMethodRegistrationAttribute] on any method, it calls ITrimmableTypeMapLogger.LogJniAddNativeMethodRegistrationAttributeError directly from the per-type scan loop. No JavaPeerInfo property is propagated; the orchestrator simply passes its logger into new JavaPeerScanner(logger).
  • The MSBuild logger maps the call to XA4251, so GenerateTrimmableTypeMap fails the build via TaskLoggingHelper.HasLoggedErrors.
  • The message instructs developers to either avoid the attribute or switch off the trimmable typemap (for example, by using the llvm-ir type map implementation), and to report the scenario at https://github.com/dotnet/android/issues so the team can evaluate whether to support it.
  • Java.InteropTests.InvokeVirtualFromConstructorTests (which uses the attribute) is permanently excluded under the trimmable typemap with an explanatory comment pointing at this policy.
  • tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csproj excludes the upstream CallVirtualFromConstructor{Base,Derived}.cs and InvokeVirtualFromConstructorTests.cs from the test assembly compile when _AndroidTypeMapImplementation == trimmable, so the device-test build can compile through the trimmable typemap generator. (The other upstream user of the attribute, TestType.cs, is already gated by #if !NO_MARSHAL_MEMBER_BUILDER_SUPPORT, which the test csproj defines.)

Tests:

  • JavaPeerScannerTests.Scan_JniAddNativeMethodRegistrationAttribute_LogsError (new) gives the scanner a recording ITrimmableTypeMapLogger and asserts it logs XA4251 for HandWrittenNativeRegistrationPeer and not for unrelated fixture types.
  • TrimmableTypeMapGeneratorTests.Execute_WithJniAddNativeMethodRegistrationAttribute_ReportsXA4251 (new) verifies the orchestrator end-to-end emits XA4251 against the same fixture.

Device validation against an Android emulator with the CoreCLRTrimmable lane:

ANDROID_SERIAL=emulator-5554 MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build \
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj \
-t:RunTestApp -c Release \
-p:_AndroidTypeMapImplementation=trimmable -p:UseMonoRuntime=false \
-nr:false -m:1

TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total, 0 errors, 0 failures, 21 ignored.

Related issues

@simonrozsivalsimonrozsival changed the title Use trimmable virtual-constructor fixtures[TrimmableTypeMap] Use trimmable virtual-constructor fixturesMay 3, 2026
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 3, 2026
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from 1467afa to e66930eCompareMay 4, 2026 18:21
@simonrozsival
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 711aeae to 7e2737bCompareMay 4, 2026 18:23
simonrozsivaland others added 3 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>
Enable the Java.Interop virtual-constructor tests in the trimmable typemap lane by swapping in Android-owned Java fixtures that use Runtime.registerNatives and generated n_* callbacks instead of ManagedPeer.
Teach the trimmable typemap scanner/model to emit native registrations for hand-written Java peers that opt into JniAddNativeMethodRegistrationAttribute.
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
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 7e2737b to dc13b42CompareMay 4, 2026 18:31
simonrozsivaland others added 7 commits May 5, 2026 11:31
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>
…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
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>
Base automatically changed from trimmable-java-proxy-object to mainMay 11, 2026 07:16
…structor
# Conflicts:
#	src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs
#	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs
@simonrozsival
simonrozsival marked this pull request as ready for review May 11, 2026 09:11
CopilotAI review requested due to automatic review settings May 11, 2026 09:11
…mmableTypeMapBuildTests
This cleanup is not related to fixing InvokeVirtualFromConstructorTests
and belongs in a separate change.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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 re-enables Java.InteropTests.InvokeVirtualFromConstructorTests for the CoreCLR trimmable typemap lane by swapping desktop-JVM Java.Interop fixtures for Android/trimmable-compatible copies and extending the trimmable typemap generator to support native registrations for hand-written Java peers.

Changes:

  • Removes the trimmable-typemap exclusion for Java.InteropTests.InvokeVirtualFromConstructorTests and adds trimmable Java/C# fixtures for CallVirtualFromConstructor*.
  • Extends the trimmable typemap scanner/model to detect JniAddNativeMethodRegistrationAttribute usage and emit proxy/registration support accordingly.
  • Adds cleanup/validation for obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts (delete during build; assert not packaged in SDK tests).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.csRe-enables InvokeVirtualFromConstructorTests by removing its name-based exclusion.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-trimmable/CallVirtualFromConstructorDerived.csAdds trimmable managed peer fixture using generated n_* callbacks + JniAddNativeMethodRegistrationAttribute.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.targetsSwitches trimmable builds to include Android-owned Java fixtures in the test JAR and exclude the desktop versions.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csprojConditionally swaps the managed CallVirtualFromConstructorDerived source between desktop and trimmable variants.
tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorDerived.javaAdds Android/trimmable Java fixture using mono.android.Runtime.registerNatives(Class) via reflection.
tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorBase.javaAdds Android/trimmable base Java fixture using registerNatives(Class) via reflection.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.csVerifies obsolete net6/trimmable_clr runtime artifacts are not shipped in the SDK pack.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.csDetects method-level JniAddNativeMethodRegistrationAttribute to inform generation decisions.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerInfo.csStores whether a peer uses JniAddNativeMethodRegistrationAttribute.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.csTreats certain DoNotGenerateAcw peers with native registrations as needing proxy/registration emission.
src/java-runtime/java-runtime.targetsDeletes obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts during build/clean.

Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Outdated
…emap
[JniAddNativeMethodRegistrationAttribute] is a legacy Java.Interop API whose
primary consumer — the jnimarshalmethod-gen build-time generator — was
removed in dotnet/java-interop#1405. The trimmable typemap deliberately does
not support this attribute.
When the scanner detects the attribute on any method, the generator emits
XA4251 telling the developer to either avoid it or switch off the trimmable
typemap (for example, by using the 'llvm-ir' type map implementation) and
report the scenario at https://github.com/dotnet/android/issues. The build
fails via TaskLoggingHelper.HasLoggedErrors.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival changed the title [TrimmableTypeMap] Use trimmable virtual-constructor fixtures[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251May 11, 2026
simonrozsivaland others added 3 commits May 11, 2026 12:05
Address review feedback:
- Drop JavaPeerInfo.HasJniAddNativeMethodRegistrationAttribute. The scanner
now takes an optional ITrimmableTypeMapLogger and reports XA4251 directly
when it encounters the attribute, instead of propagating a bool the rest
of the pipeline doesn't otherwise need.
- Drop the orchestrator's post-scan loop; TrimmableTypeMapGenerator just
passes its logger into JavaPeerScanner.
- Reset external/Java.Interop and external/xamarin-android-tools to the
SHAs on main; this PR doesn't need either submodule moved.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t/dot/jni/test/GetThis.java
This file is unrelated to the XA4251 work; it was accidentally removed during
an earlier 'git rm -r java-trimmable' cleanup. It's still needed by
JavaObjectTest.DisposeAccessesThis under the trimmable typemap.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The upstream Java.Interop test fixture CallVirtualFromConstructorDerived
uses [JniAddNativeMethodRegistrationAttribute]. Now that the trimmable
typemap refuses that attribute with XA4251, the offending sources need to
be excluded from the test assembly when building for the trimmable type
map; otherwise the build cannot reach the device tests at all.
Validated locally:
ANDROID_SERIAL=emulator-5554 MSBUILDDISABLENODEREUSE=1 \
./dotnet-local.sh build \
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj \
-t:RunTestApp -c Release \
-p:_AndroidTypeMapImplementation=trimmable \
-p:UseMonoRuntime=false -nr:false -m:1
TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total,
0 errors, 0 failures, 21 ignored.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Code-review caught that the prior placement of the XA4251 check sat *after*
the scanner's per-type filtering, so a type carrying the attribute but no
[Register] (and not extending a Java peer) would slip past the diagnostic
and the build would silently succeed.
Hoist the check to immediately after the <Module> skip so it fires uniformly
for every non-<Module> type, regardless of whether the type would otherwise
have been added to the typemap. Add a NonPeerNativeRegistration fixture to
the scanner test to guard the regression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 7ad46cf to 7d607c5CompareMay 11, 2026 10:53
…bute
Address Copilot reviewer feedback on the per-type method-attribute walk.
AssemblyIndex.Build now does a cheap pass over the TypeReferences and
TypeDefinitions tables to set MayUseJniAddNativeMethodRegistrationAttribute,
and the scanner short-circuits the per-method walk in the overwhelmingly
common case where the assembly neither imports nor declares the attribute.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
simonrozsival added a commit that referenced this pull request May 11, 2026
Squashed prerequisites from PR #11274 (trimmable-virtual-constructor):
reject [JniAddNativeMethodRegistrationAttribute] with XA4251 in the
trimmable typemap path and exclude the upstream
InvokeVirtualFromConstructor fixtures so the trimmable test assembly
builds.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 12, 2026
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Outdated
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Outdated
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Outdated
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot address reviewer's comments

CopilotAI commented May 13, 2026

Copy link
Copy Markdown
Contributor

@copilot address reviewer's comments

Addressed the reviewer feedback with namespace-aware matching in both the fast-check and per-method attribute match, plus regression coverage for same-name attributes in other namespaces. See commits d779cec and ed91def.

simonrozsivaland others added 2 commits May 13, 2026 14:24
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve merge conflicts: combine packageNamingPolicy and logger
parameters in JavaPeerScanner constructor.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jonathanpeppers
jonathanpeppers merged commit 61a5839 into mainMay 14, 2026
3 checks passed
@jonathanpeppers
jonathanpeppers deleted the trimmable-virtual-constructor branch May 14, 2026 20:53
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 14, 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 thisnice-to-haveready-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] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251 - #11274

Merged
jonathanpeppers merged 21 commits into
mainfrom
trimmable-virtual-constructor
May 14, 2026
Merged

[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251#11274
jonathanpeppers merged 21 commits into
mainfrom
trimmable-virtual-constructor

Conversation

@simonrozsival

@simonrozsivalsimonrozsival commented May 3, 2026

Copy link
Copy Markdown
Member

Refuses [JniAddNativeMethodRegistrationAttribute] in the trimmable typemap.

[JniAddNativeMethodRegistrationAttribute] is a legacy Java.Interop public API. Its primary consumer — the jnimarshalmethod-gen build-time generator that used to emit [JniAddNativeMethodRegistrationAttribute] static void __RegisterNativeMembers stubs on every JCW type — was removed in dotnet/java-interop#1405. The only remaining in-tree uses are Java.Interop's own JavaProxyObject / JavaProxyThrowable infrastructure types (already bypassed in the trimmable path by #11271) and a couple of upstream Java.Interop test fixtures. Supporting it in the trimmable typemap would mean adding scanner + ModelBuilder support for an obsolete code path with no in-tree consumers and a near-zero customer base.

This PR makes the design decision explicit:

  • JavaPeerScanner now takes an optional ITrimmableTypeMapLogger. When it encounters [JniAddNativeMethodRegistrationAttribute] on any method, it calls ITrimmableTypeMapLogger.LogJniAddNativeMethodRegistrationAttributeError directly from the per-type scan loop. No JavaPeerInfo property is propagated; the orchestrator simply passes its logger into new JavaPeerScanner(logger).
  • The MSBuild logger maps the call to XA4251, so GenerateTrimmableTypeMap fails the build via TaskLoggingHelper.HasLoggedErrors.
  • The message instructs developers to either avoid the attribute or switch off the trimmable typemap (for example, by using the llvm-ir type map implementation), and to report the scenario at https://github.com/dotnet/android/issues so the team can evaluate whether to support it.
  • Java.InteropTests.InvokeVirtualFromConstructorTests (which uses the attribute) is permanently excluded under the trimmable typemap with an explanatory comment pointing at this policy.
  • tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csproj excludes the upstream CallVirtualFromConstructor{Base,Derived}.cs and InvokeVirtualFromConstructorTests.cs from the test assembly compile when _AndroidTypeMapImplementation == trimmable, so the device-test build can compile through the trimmable typemap generator. (The other upstream user of the attribute, TestType.cs, is already gated by #if !NO_MARSHAL_MEMBER_BUILDER_SUPPORT, which the test csproj defines.)

Tests:

  • JavaPeerScannerTests.Scan_JniAddNativeMethodRegistrationAttribute_LogsError (new) gives the scanner a recording ITrimmableTypeMapLogger and asserts it logs XA4251 for HandWrittenNativeRegistrationPeer and not for unrelated fixture types.
  • TrimmableTypeMapGeneratorTests.Execute_WithJniAddNativeMethodRegistrationAttribute_ReportsXA4251 (new) verifies the orchestrator end-to-end emits XA4251 against the same fixture.

Device validation against an Android emulator with the CoreCLRTrimmable lane:

ANDROID_SERIAL=emulator-5554 MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build \
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj \
-t:RunTestApp -c Release \
-p:_AndroidTypeMapImplementation=trimmable -p:UseMonoRuntime=false \
-nr:false -m:1

TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total, 0 errors, 0 failures, 21 ignored.

Related issues

@simonrozsivalsimonrozsival changed the title Use trimmable virtual-constructor fixtures[TrimmableTypeMap] Use trimmable virtual-constructor fixturesMay 3, 2026
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 3, 2026
@simonrozsival
simonrozsivalforce-pushed the trimmable-java-proxy-object branch from 1467afa to e66930eCompareMay 4, 2026 18:21
@simonrozsival
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 711aeae to 7e2737bCompareMay 4, 2026 18:23
simonrozsivaland others added 3 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>
Enable the Java.Interop virtual-constructor tests in the trimmable typemap lane by swapping in Android-owned Java fixtures that use Runtime.registerNatives and generated n_* callbacks instead of ManagedPeer.
Teach the trimmable typemap scanner/model to emit native registrations for hand-written Java peers that opt into JniAddNativeMethodRegistrationAttribute.
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
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 7e2737b to dc13b42CompareMay 4, 2026 18:31
simonrozsivaland others added 7 commits May 5, 2026 11:31
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>
…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
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>
Base automatically changed from trimmable-java-proxy-object to mainMay 11, 2026 07:16
…structor
# Conflicts:
#	src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs
#	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs
@simonrozsival
simonrozsival marked this pull request as ready for review May 11, 2026 09:11
CopilotAI review requested due to automatic review settings May 11, 2026 09:11
…mmableTypeMapBuildTests
This cleanup is not related to fixing InvokeVirtualFromConstructorTests
and belongs in a separate change.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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 re-enables Java.InteropTests.InvokeVirtualFromConstructorTests for the CoreCLR trimmable typemap lane by swapping desktop-JVM Java.Interop fixtures for Android/trimmable-compatible copies and extending the trimmable typemap generator to support native registrations for hand-written Java peers.

Changes:

  • Removes the trimmable-typemap exclusion for Java.InteropTests.InvokeVirtualFromConstructorTests and adds trimmable Java/C# fixtures for CallVirtualFromConstructor*.
  • Extends the trimmable typemap scanner/model to detect JniAddNativeMethodRegistrationAttribute usage and emit proxy/registration support accordingly.
  • Adds cleanup/validation for obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts (delete during build; assert not packaged in SDK tests).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.csRe-enables InvokeVirtualFromConstructorTests by removing its name-based exclusion.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-trimmable/CallVirtualFromConstructorDerived.csAdds trimmable managed peer fixture using generated n_* callbacks + JniAddNativeMethodRegistrationAttribute.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.targetsSwitches trimmable builds to include Android-owned Java fixtures in the test JAR and exclude the desktop versions.
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csprojConditionally swaps the managed CallVirtualFromConstructorDerived source between desktop and trimmable variants.
tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorDerived.javaAdds Android/trimmable Java fixture using mono.android.Runtime.registerNatives(Class) via reflection.
tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorBase.javaAdds Android/trimmable base Java fixture using registerNatives(Class) via reflection.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.csVerifies obsolete net6/trimmable_clr runtime artifacts are not shipped in the SDK pack.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.csDetects method-level JniAddNativeMethodRegistrationAttribute to inform generation decisions.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerInfo.csStores whether a peer uses JniAddNativeMethodRegistrationAttribute.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.csTreats certain DoNotGenerateAcw peers with native registrations as needing proxy/registration emission.
src/java-runtime/java-runtime.targetsDeletes obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts during build/clean.

Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Outdated
…emap
[JniAddNativeMethodRegistrationAttribute] is a legacy Java.Interop API whose
primary consumer — the jnimarshalmethod-gen build-time generator — was
removed in dotnet/java-interop#1405. The trimmable typemap deliberately does
not support this attribute.
When the scanner detects the attribute on any method, the generator emits
XA4251 telling the developer to either avoid it or switch off the trimmable
typemap (for example, by using the 'llvm-ir' type map implementation) and
report the scenario at https://github.com/dotnet/android/issues. The build
fails via TaskLoggingHelper.HasLoggedErrors.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival changed the title [TrimmableTypeMap] Use trimmable virtual-constructor fixtures[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251May 11, 2026
simonrozsivaland others added 3 commits May 11, 2026 12:05
Address review feedback:
- Drop JavaPeerInfo.HasJniAddNativeMethodRegistrationAttribute. The scanner
now takes an optional ITrimmableTypeMapLogger and reports XA4251 directly
when it encounters the attribute, instead of propagating a bool the rest
of the pipeline doesn't otherwise need.
- Drop the orchestrator's post-scan loop; TrimmableTypeMapGenerator just
passes its logger into JavaPeerScanner.
- Reset external/Java.Interop and external/xamarin-android-tools to the
SHAs on main; this PR doesn't need either submodule moved.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t/dot/jni/test/GetThis.java
This file is unrelated to the XA4251 work; it was accidentally removed during
an earlier 'git rm -r java-trimmable' cleanup. It's still needed by
JavaObjectTest.DisposeAccessesThis under the trimmable typemap.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The upstream Java.Interop test fixture CallVirtualFromConstructorDerived
uses [JniAddNativeMethodRegistrationAttribute]. Now that the trimmable
typemap refuses that attribute with XA4251, the offending sources need to
be excluded from the test assembly when building for the trimmable type
map; otherwise the build cannot reach the device tests at all.
Validated locally:
ANDROID_SERIAL=emulator-5554 MSBUILDDISABLENODEREUSE=1 \
./dotnet-local.sh build \
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj \
-t:RunTestApp -c Release \
-p:_AndroidTypeMapImplementation=trimmable \
-p:UseMonoRuntime=false -nr:false -m:1
TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total,
0 errors, 0 failures, 21 ignored.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Code-review caught that the prior placement of the XA4251 check sat *after*
the scanner's per-type filtering, so a type carrying the attribute but no
[Register] (and not extending a Java peer) would slip past the diagnostic
and the build would silently succeed.
Hoist the check to immediately after the <Module> skip so it fires uniformly
for every non-<Module> type, regardless of whether the type would otherwise
have been added to the typemap. Add a NonPeerNativeRegistration fixture to
the scanner test to guard the regression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the trimmable-virtual-constructor branch from 7ad46cf to 7d607c5CompareMay 11, 2026 10:53
…bute
Address Copilot reviewer feedback on the per-type method-attribute walk.
AssemblyIndex.Build now does a cheap pass over the TypeReferences and
TypeDefinitions tables to set MayUseJniAddNativeMethodRegistrationAttribute,
and the scanner short-circuits the per-method walk in the overwhelmingly
common case where the assembly neither imports nor declares the attribute.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
simonrozsival added a commit that referenced this pull request May 11, 2026
Squashed prerequisites from PR #11274 (trimmable-virtual-constructor):
reject [JniAddNativeMethodRegistrationAttribute] with XA4251 in the
trimmable typemap path and exclude the upstream
InvokeVirtualFromConstructor fixtures so the trimmable test assembly
builds.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 12, 2026
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Outdated
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Outdated
Comment threadsrc/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Outdated
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

@copilot address reviewer's comments

CopilotAI commented May 13, 2026

Copy link
Copy Markdown
Contributor

@copilot address reviewer's comments

Addressed the reviewer feedback with namespace-aware matching in both the fast-check and per-method attribute match, plus regression coverage for same-name attributes in other namespaces. See commits d779cec and ed91def.

simonrozsivaland others added 2 commits May 13, 2026 14:24
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve merge conflicts: combine packageNamingPolicy and logger
parameters in JavaPeerScanner constructor.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jonathanpeppers
jonathanpeppers merged commit 61a5839 into mainMay 14, 2026
3 checks passed
@jonathanpeppers
jonathanpeppers deleted the trimmable-virtual-constructor branch May 14, 2026 20:53
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 14, 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 thisnice-to-haveready-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