[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251#11274
[TrimmableTypeMap] Refuse [JniAddNativeMethodRegistrationAttribute] with XA4251#11274simonrozsival wants to merge 18 commits into
Conversation
1467afa to
e66930e
Compare
711aeae to
7e2737b
Compare
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>
e66930e to
0644b70
Compare
7e2737b to
dc13b42
Compare
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>
…to pick up CI fixes
…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
…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>
There was a problem hiding this comment.
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.InvokeVirtualFromConstructorTestsand adds trimmable Java/C# fixtures forCallVirtualFromConstructor*. - Extends the trimmable typemap scanner/model to detect
JniAddNativeMethodRegistrationAttributeusage and emit proxy/registration support accordingly. - Adds cleanup/validation for obsolete
java_runtime_*_net6/java_runtime_trimmable_clrartifacts (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
| File | Description |
|---|---|
| tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs | Re-enables InvokeVirtualFromConstructorTests by removing its name-based exclusion. |
| tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-trimmable/CallVirtualFromConstructorDerived.cs | Adds trimmable managed peer fixture using generated n_* callbacks + JniAddNativeMethodRegistrationAttribute. |
| tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.targets | Switches 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.csproj | Conditionally swaps the managed CallVirtualFromConstructorDerived source between desktop and trimmable variants. |
| tests/Mono.Android-Tests/Java.Interop-Tests/java-trimmable/net/dot/jni/test/CallVirtualFromConstructorDerived.java | Adds 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.java | Adds Android/trimmable base Java fixture using registerNatives(Class) via reflection. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs | Verifies obsolete net6/trimmable_clr runtime artifacts are not shipped in the SDK pack. |
| src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs | Detects method-level JniAddNativeMethodRegistrationAttribute to inform generation decisions. |
| src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerInfo.cs | Stores whether a peer uses JniAddNativeMethodRegistrationAttribute. |
| src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.cs | Treats certain DoNotGenerateAcw peers with native registrations as needing proxy/registration emission. |
| src/java-runtime/java-runtime.targets | Deletes obsolete java_runtime_*_net6 / java_runtime_trimmable_clr artifacts during build/clean. |
| #nullable enable | ||
|
|
||
| using System; | ||
| using System.Runtime.CompilerServices; |
There was a problem hiding this comment.
The file this comment was on (tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-trimmable/CallVirtualFromConstructorDerived.cs) has since been removed — this PR no longer adds Java.Interop-trimmable fixtures for the attribute; we refuse the attribute outright with XA4251 instead.
| var isInterface = (typeDef.Attributes & TypeAttributes.Interface) != 0; | ||
| var isAbstract = (typeDef.Attributes & TypeAttributes.Abstract) != 0; | ||
| var isGenericDefinition = typeDef.GetGenericParameters ().Count > 0; | ||
| var hasJniAddNativeMethodRegistrationAttribute = HasJniAddNativeMethodRegistrationAttribute (typeDef, index); |
There was a problem hiding this comment.
Addressed in 1a71bb3. The doNotGenerateAcw short-circuit no longer applies after the rework — XA4251 should fire even for non-peer types — but the per-type method-attribute walk is now gated on a cheap assembly-level fast-check (AssemblyIndex.MayUseJniAddNativeMethodRegistrationAttribute), so the inner loop runs only when the assembly's TypeRefs / TypeDefs actually mention the attribute name.
…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>
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>
7ad46cf to
7d607c5
Compare
…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>
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>
Refuses
[JniAddNativeMethodRegistrationAttribute]in the trimmable typemap.[JniAddNativeMethodRegistrationAttribute]is a legacy Java.Interop public API. Its primary consumer — thejnimarshalmethod-genbuild-time generator that used to emit[JniAddNativeMethodRegistrationAttribute] static void __RegisterNativeMembersstubs on every JCW type — was removed in dotnet/java-interop#1405. The only remaining in-tree uses are Java.Interop's ownJavaProxyObject/JavaProxyThrowableinfrastructure 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:
JavaPeerScannernow takes an optionalITrimmableTypeMapLogger. When it encounters[JniAddNativeMethodRegistrationAttribute]on any method, it callsITrimmableTypeMapLogger.LogJniAddNativeMethodRegistrationAttributeErrordirectly from the per-type scan loop. NoJavaPeerInfoproperty is propagated; the orchestrator simply passes its logger intonew JavaPeerScanner(logger).XA4251, soGenerateTrimmableTypeMapfails the build viaTaskLoggingHelper.HasLoggedErrors.llvm-irtype 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.csprojexcludes the upstreamCallVirtualFromConstructor{Base,Derived}.csandInvokeVirtualFromConstructorTests.csfrom 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 recordingITrimmableTypeMapLoggerand asserts it logsXA4251forHandWrittenNativeRegistrationPeerand not for unrelated fixture types.TrimmableTypeMapGeneratorTests.Execute_WithJniAddNativeMethodRegistrationAttribute_ReportsXA4251(new) verifies the orchestrator end-to-end emitsXA4251against the same fixture.Device validation against an Android emulator with the CoreCLRTrimmable lane:
TestResult-Mono.Android.NET_Tests-ReleaseCoreCLRTrimmable.xml: 888 total, 0 errors, 0 failures, 21 ignored.Related issues