Skip to content

[Java.Interop] Retire obsolete Java wrapper scaffolding - #13080

Merged
simonrozsival merged 3 commits into
mainfrom
simonrozsival-generated-java-cleanup-analysis
Oct 12, 2026
Merged

simonrozsival merged 3 commits into
mainfrom
simonrozsival-generated-java-cleanup-analysis

Conversation

@simonrozsival

@simonrozsival simonrozsival commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Summary

Retire the remaining legacy Java callable wrapper emitter and obsolete Java bootstrap artifacts for the .NET 12 cleanup. Current applications already use the trimmable typemap's separate Java generator; the old emitter still produced __md_methods, Runtime.register, and TypeManager.Activate references whose runtime consumers were removed.

  • Remove the legacy CallableWrapper* model/writers, reader/writer options, classifier/style selector, Cecil/XML adapters, standalone jcw-gen, and obsolete golden-output tests. Preserve shared naming/scanning/hash/type-name mapping utilities and supported XAJavaInterop1 C# binding generation.
  • Remove abstract Java constructor bridges, deferred constructor bridges together with unused managed UCO bodies/native-table rows, and uncalled deferred-registration helpers. Preserve Java constructor/super sequencing, callback registrations, and managed CreateInstance activation.
  • Ship only the retained trimmable runtime JAR/DEX pair. Retire alternate artifacts, unused DebugRuntime/BuildConfig/environment scaffolding, old context-management JNI declarations, vestigial bootstrap APIs, and the unused embedded registration template.
  • Move the actual JNI header producer to the retained output, wire the Java fixture compiler to the retained JAR, and rebuild runtime JAR contents without stale removed classes. Remove exact retired artifact names before both Build and Clean, including no-op builds.

Compatibility and scope

The public legacy tooling/bootstrap removals are intentional compatibility breaks, explicitly authorized for this cleanup. Custom tooling that used the retired emitter/CLI or old Java runtime APIs/artifacts must migrate to the current pipeline. The tooling assembly's still-live utilities remain shipped.

Nonempty registerNatives/UCO tables, callback-format/connector metadata, concrete constructor guards, GC peers/reference edges, shared Context, runtime providers, real environment configuration, and both runtimes' conservative field-name retention remain intact. The unproven IntentService shim and conditional empty-registration/alias-retention candidates are excluded.

The intended release is .NET 12; this cleanup does not change configured TFMs or SDK/package pins. This branch includes main through abe9f433cea1df41d368039aca787edbd91c1512, not sibling cleanup branches. The merged #13060 emitter simplification caused three modify/delete conflicts, resolved by retaining this PR's intentional emitter, legacy-test, and CLI deletions. Upstream Throwable ownership, #13062 field-name retention, native bootstrap/configuration, NDK tooling, and R8 changes remain intact.

Latest-main merge validation

Merge commit dd3250b19270f6e167054178d69ab48d76a25d58 has parents 7b60efd96de8fd85e49a9038f2a03902a3324ca7 and abe9f433cea1df41d368039aca787edbd91c1512. No remaining conflict markers or unmerged paths exist. Whole-path comparisons confirm upstream Throwable ownership, field-retention, NDK, native-host, R8, and related tests were not altered by the resolution.

The coherent SDK refresh below rebuilt both native hosts, managed runtime/bindings, generator/task dependencies, and host tests together; packaging checks did not use a managed-only refresh with stale native binaries. Commands ran in this worktree, with -m:2, no reused build servers, and a session-only Ninja wrapper executing the prepared Ninja with -j2. No full prepare/all or device operation was needed for this merge.

Exact command / coverage Result on merged sources
dotnet test external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers-Tests.csproj -c Release -m:2 -nr:false -v minimal Passed: 22, no skips.
JAVA_HOME=/Users/simon/android-toolchain/jdk-25 dotnet test external/Java.Interop/tests/generator-Tests/generator-Tests.csproj -c Release -m:2 -nr:false -v minimal Passed: 478, no skips.
JAVA_HOME=/Users/simon/android-toolchain/jdk-25 dotnet test src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/Microsoft.Android.Build.Tasks.Tests.csproj -c Release -m:2 -nr:false -v minimal -p:_NativeAotLlvmReadObjPath=/Users/simon/android-toolchain/ndk/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readobj --filter 'FullyQualifiedName~TrimmableTypeMap|FullyQualifiedName~TypeMapProguard|FullyQualifiedName~NativeAotBootstrap|FullyQualifiedName~JavaRuntimeTargetsTests|FullyQualifiedName~ResourcesTests|FullyQualifiedName~WrapAssemblyStoresAsSharedLibraries' Passed: 169, no skips, including Java/native-table shapes, cleanup, bootstrap and retained typemap/NDK coverage.
./dotnet-local.sh build build-tools/scripts/Prepare.proj -t:BuildExtraApiLevels -c Release -m:2 -nr:false --disable-build-servers -v minimal -p:NinjaPath=/Users/simon/.copilot/session-state/209b09d7-6866-4a15-a7a5-610402d16ce9/files/bounded-ninja.sh Passed: refreshed API 37.1/37.2 bindings and compatibility gates; 62 warnings, zero errors.
./dotnet-local.sh build build-tools/create-packs/Microsoft.Android.Sdk.proj -t:ConfigureLocalWorkload -c Release -m:2 -nr:false --disable-build-servers -v minimal Passed: coherent local runtime/reference/workload packaging; zero warnings/errors.
JAVA_HOME=/Users/simon/android-toolchain/jdk-25 dotnet test src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/Microsoft.Android.Build.Tasks.Tests.csproj -c Release -m:2 -nr:false -v minimal -p:_NativeAotLlvmReadObjPath=/Users/simon/android-toolchain/ndk/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readobj --filter 'FullyQualifiedName~GenerateTrimmableTypeMap|FullyQualifiedName~JavaRuntimeTargetsTests' Passed: 26, no skips; rerun with refreshed merged managed SDK inputs.
./dotnet-local.sh test bin/TestRelease/net10.0/Xamarin.Android.Build.Tests.dll --filter 'FullyQualifiedName~Build_WithTrimmableTypeMap_Succeeds|FullyQualifiedName~BindingCallbackFormatSupportsDefaultConsumer|FullyQualifiedName~RetainedTypeMapRulesDriveR8|FullyQualifiedName~TrimmableTypeMap_RuntimeArtifacts_ArePackagedInSdk|FullyQualifiedName~Build_WithExportAndExportField_GeneratesJcwAndTypeMap|FullyQualifiedName~Build_WithTrimmableTypeMap_AbstractTypeWithProtectedCtor|FullyQualifiedName~AndroidNdkToolsTests|FullyQualifiedName~GenerateNativeApplicationConfigSourcesTests|FullyQualifiedName~R8Tests' --logger 'trx;LogFileName=merge-host.trx' --results-directory /Users/simon/.copilot/session-state/209b09d7-6866-4a15-a7a5-610402d16ce9/files/merge-host-results Passed: 68, no skips, including CoreCLR/NativeAOT APK output and R8/native bootstrap/NDK/runtime artifact checks.

The native/managed refresh command completed successfully for every listed project:

for project in \
  src/native/native-clr.csproj \
  src/native/native-nativeaot.csproj \
  src/Mono.Android.Runtime/Mono.Android.Runtime.csproj \
  src/Mono.Android/Mono.Android.csproj \
  src/Mono.Android.Export/Mono.Android.Export.csproj \
  src/Microsoft.Android.Runtime.NativeAOT/Microsoft.Android.Runtime.NativeAOT.csproj \
  src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj
do
  ./dotnet-local.sh build "$project" -c Release -m:2 -nr:false --disable-build-servers -v minimal \
    -p:NinjaPath=/Users/simon/.copilot/session-state/209b09d7-6866-4a15-a7a5-610402d16ce9/files/bounded-ninja.sh || exit $?
done

The earlier full device results below apply to the original implementation commit, not to this latest-main merge; no post-merge device validation is claimed.

Original implementation validation

Builds used the repository's MSBUILD_ARGS=-m:2 mechanism and a session-local NinjaPath override that executes the prepared real Ninja with -j2. The wrapper is not a repository change.

Command / coverage Actual result before latest-main merge
make prepare CONFIGURATION=Release MSBUILD_ARGS='-m:2' Passed, zero warnings/errors.
make all CONFIGURATION=Release MSBUILD_ARGS='-m:2 -p:NinjaPath=/Users/simon/.copilot/session-state/209b09d7-6866-4a15-a7a5-610402d16ce9/files/bounded-ninja.sh' Solution compilation/API gate passed; initial local workload setup failed because the default build lacked API 37.1 references.
./dotnet-local.sh build build-tools/scripts/Prepare.proj -t:BuildExtraApiLevels -c Release -v minimal -m:2 -p:NinjaPath=/Users/simon/.copilot/session-state/209b09d7-6866-4a15-a7a5-610402d16ce9/files/bounded-ninja.sh Passed; produced this worktree's API 37.1/37.2 references and ran compatibility gates.
Same bounded make all command after extra-API build Passed, including local workload setup; final setup zero warnings/errors.
dotnet test external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers-Tests.csproj -c Release -m:2 -v minimal Passed: 22 naming/scanning tests, no skips.
JAVA_HOME=/Users/simon/android-toolchain/jdk-25 dotnet test external/Java.Interop/tests/generator-Tests/generator-Tests.csproj -c Release -m:2 -v minimal Passed: 478 supported binding-generator tests, no skips.
JAVA_HOME=/Users/simon/android-toolchain/jdk-25 dotnet test src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/Microsoft.Android.Build.Tasks.Tests.csproj -c Release -m:2 -v minimal --filter 'FullyQualifiedName~TrimmableTypeMap|FullyQualifiedName~TypeMapProguard|FullyQualifiedName~NativeAotBootstrap|FullyQualifiedName~ResourcesTests' Passed: 156 tests; four LLVM-dependent cases initially skipped.
JAVA_HOME=/Users/simon/android-toolchain/jdk-25 dotnet test src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/Microsoft.Android.Build.Tasks.Tests.csproj -c Release -m:2 -v minimal -p:_NativeAotLlvmReadObjPath=/Users/simon/android-toolchain/ndk/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readobj --filter 'FullyQualifiedName~NativeObjectTargetUnionsRidsAndHonorsDisabledTrimming|FullyQualifiedName~NativeAotModeRoundTripsCannotReuseWrongRules|FullyQualifiedName~UnoptimizedNativeAotReadsObjectWithoutGraphs' Passed: all four formerly skipped cases, no skips.
./dotnet-local.sh test bin/TestRelease/net10.0/Xamarin.Android.Build.Tests.dll --filter 'FullyQualifiedName~TrimmableTypeMapBuildTests|FullyQualifiedName~GenerateCoreClrRuntimeProviderSourcesTests|FullyQualifiedName~CopyResourceTests|FullyQualifiedName~GeneratePackageManagerJava|FullyQualifiedName~R8Tests' Passed: 217 host integration tests, no skips.
./dotnet-local.sh build tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj -c Release -m:2 -p:RuntimeIdentifier=android-arm64 -p:PublishAot=false -p:NinjaPath=/Users/simon/.copilot/session-state/209b09d7-6866-4a15-a7a5-610402d16ce9/files/bounded-ninja.sh Passed: CoreCLR fixture, 38 warnings/zero errors.
Same fixture build with -p:PublishAot=true -p:IlcSingleThreaded=true Passed: NativeAOT fixture, 11 warnings/zero errors.
./dotnet-local.sh build src/java-runtime/java-runtime.csproj -c Release -m:2 -v normal Passed; unchanged Java JAR/header and D8 generation skipped correctly.

The eight-case regression covers abstract/concrete, deferred/eager, and callback/no-callback combinations, asserting both emitted Java calls/declarations and generated managed UCO/native registration output. A separate session-only comparison compiled the original emitters against the same model and saved eight pairs of actual Java/managed PE outputs: ordinary concrete registrations are unchanged, deferred constructor rows disappear, and abstract callback tables remain unchanged.

Actual retained JAR contents and generated JNI header were inspected. Runtime/GC/package-manager classes remain, removed classes/APIs are absent, and the JNI header contains live initInternal/registerNatives declarations.

Original on-device runtime validation

At implementation commit 8f16c4a514eae7cba55293a65ae98aa511330ef3, before the latest-main merge, both full suites ran on the exclusively selected API 36 arm64 emulator emulator-5554, with no physical-device operations. CoreCLR passed 933, skipped 8, failed 0 (941 total); NativeAOT passed 879, skipped 7, failed 0 (886 total). Skips are existing test/runtime limitations or unavailable network access; NativeAOT intentionally skips the CoreCLR GC event-emission test.

TRX inspection confirms these relevant checks passed in each original runtime run: constructor activation 38, virtual constructor/reentrancy 3, direct callbacks 2, exports 9, trimmable runtime coverage 10, manifest startup 1, GC bridge 11, peer identity 5, managed-object proxies 10, and application 4. Only the owned test package was uninstalled afterward and the device lease was released.

Exact CoreCLR commands:

ANDROID_SERIAL=emulator-5554 ./dotnet-local.sh build -t:Install -c Release -m:2 -p:RuntimeIdentifier=android-arm64 -p:PublishAot=false '-p:AdbTarget=-s emulator-5554' tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj
(
  cd tests/Mono.Android-Tests/Mono.Android-Tests
  ANDROID_SERIAL=emulator-5554 ../../../dotnet-local.sh test Mono.Android.NET-Tests.csproj --no-build -c Release -p:RuntimeIdentifier=android-arm64 -p:PublishAot=false '-p:AdbTarget=-s emulator-5554' --device emulator-5554 --report-trx --results-directory /Users/simon/.copilot/session-state/209b09d7-6866-4a15-a7a5-610402d16ce9/files/device-results/coreclr
)

Exact NativeAOT commands:

ANDROID_SERIAL=emulator-5554 ./dotnet-local.sh build -t:Install -c Release -m:2 -p:RuntimeIdentifier=android-arm64 -p:PublishAot=true -p:IlcSingleThreaded=true '-p:AdbTarget=-s emulator-5554' tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj
(
  cd tests/Mono.Android-Tests/Mono.Android-Tests
  ANDROID_SERIAL=emulator-5554 ../../../dotnet-local.sh test Mono.Android.NET-Tests.csproj --no-build -c Release -p:RuntimeIdentifier=android-arm64 -p:PublishAot=true -p:IlcSingleThreaded=true '-p:AdbTarget=-s emulator-5554' --device emulator-5554 --report-trx --results-directory /Users/simon/.copilot/session-state/209b09d7-6866-4a15-a7a5-610402d16ce9/files/device-results/nativeaot
)

Pull Request
title and
description
should follow the
commit-messages.md workflow documentation, and in particular should include:

  • Useful description of why the change is necessary.
  • Links to issues fixed
  • Unit tests

Remove the legacy JCW emitter and standalone tool whose output still
references retired registration and activation APIs.  Preserve the
shared naming utilities and current trimmable registration pipeline.

Remove unused abstract/deferred constructor bridges and bootstrap
artifacts, wire the retained runtime JAR/header producer, and document
intentional tooling compatibility removals.  Validate output/native
table agreement, SDK/API gates, host coverage, and both runtime suites.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 12, 2026 09:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Retired artifacts can survive incremental builds, and the error catalog retains an obsolete XA4217 entry.

2 open findings
What changed in this PR

Retires the obsolete Java callable-wrapper pipeline and consolidates runtime generation around the trimmable typemap implementation.

Changes:

  • Removes legacy JCW tooling, models, adapters, tests, and bootstrap APIs.
  • Eliminates unused abstract/deferred constructor bridges with regression coverage.
  • Ships only the trimmable runtime JAR/DEX and updates consumers and documentation.
File Description
src/​Xamarin.Android.Build.Tasks/​Xamarin.Android.Common.targets Removes the obsolete debug-runtime property.
src/​Xamarin.Android.Build.Tasks/​Tests/​Xamarin.Android.Build.Tests/​TrimmableTypeMapBuildTests.cs Verifies retained and retired runtime artifacts.
src/​Xamarin.Android.Build.Tasks/​Tests/​Xamarin.Android.Build.Tests/​Tasks/​CopyResourceTests.cs Verifies the removed registration template is unavailable.
src/​Xamarin.Android.Build.Tasks/​Resources/​MonoRuntimeProvider.Bundled.java Removes a stale legacy-generator comment.
src/​Xamarin.Android.Build.Tasks/​Resources/​ApplicationRegistration.java Deletes the obsolete embedded template.
src/​Mono.Android/​Mono.Android.slnf Removes jcw-gen.
src/​Microsoft.Android.Sdk.TrimmableTypeMap/​TrimmableTypeMapTypes.cs Updates provider-generation documentation.
src/​Microsoft.Android.Sdk.TrimmableTypeMap/​Scanner/​JavaPeerScanner.cs Removes legacy-emitter references.
src/​Microsoft.Android.Sdk.TrimmableTypeMap/​Generator/​ModelBuilder.cs Omits unused constructor UCOs.
src/​Microsoft.Android.Sdk.TrimmableTypeMap/​Generator/​ManifestGenerator.cs Updates provider documentation.
src/​Microsoft.Android.Sdk.TrimmableTypeMap/​Generator/​JcwJavaSourceGenerator.cs Omits invalid constructor bridges and empty helpers.
src/​Microsoft.Android.Build.Tasks/​Tests/​Microsoft.Android.Build.Tasks.Tests/​GenerateTrimmableTypeMapTests.cs Adds constructor/registration regression coverage.
src/​java-runtime/​java/​mono/​android/​Runtime.java Removes obsolete JNI declarations.
src/​java-runtime/​java/​mono/​android/​release/​BuildConfig.java Deletes obsolete runtime configuration.
src/​java-runtime/​java/​mono/​android/​release-net6/​BuildConfig.java Deletes obsolete runtime configuration.
src/​java-runtime/​java/​mono/​android/​MonoPackageManager.java Removes the legacy package manager.
src/​java-runtime/​java/​mono/​android/​MonoPackageManager_Resources.java Removes unused dependency metadata.
src/​java-runtime/​java/​mono/​android/​DebugRuntime.java Removes obsolete debug bootstrap APIs.
src/​java-runtime/​java/​mono/​android/​debug/​BuildConfig.java Deletes obsolete runtime configuration.
src/​java-runtime/​java/​mono/​android/​debug-net6/​BuildConfig.java Deletes obsolete runtime configuration.
src/​java-runtime/​java/​mono/​android/​clr/​MonoPackageManager.java Removes vestigial APIs and imports.
src/​java-runtime/​java/​mono/​android/​app/​XamarinAndroidEnvironmentVariables.java Deletes the unused environment placeholder.
src/​java-runtime/​java-runtime.targets Builds only the trimmable runtime artifacts.
Microsoft.Android.slnx Removes jcw-gen.
external/​Java.Interop/​tools/​jcw-gen/​jcw-gen.slnf Deletes the retired tool solution filter.
external/​Java.Interop/​tools/​jcw-gen/​jcw-gen.csproj Deletes the retired tool project.
external/​Java.Interop/​tools/​jcw-gen/​App.cs Deletes the retired CLI.
external/​Java.Interop/​tests/​Java.Interop.Tools.JavaCallableWrappers-Tests/​Java.Interop.Tools.JavaCallableWrappers/​XmlImporterTests.cs Removes obsolete adapter tests.
external/​Java.Interop/​tests/​Java.Interop.Tools.JavaCallableWrappers-Tests/​Java.Interop.Tools.JavaCallableWrappers/​JavaCallableWrapperGeneratorTests.cs Removes obsolete emitter tests.
external/​Java.Interop/​src/​Java.Interop.Tools.JavaCallableWrappers/​Java.Interop.Tools.JavaCallableWrappers/​JavaPeerStyle.cs Removes the retired style selector.
external/​Java.Interop/​src/​Java.Interop.Tools.JavaCallableWrappers/​Java.Interop.Tools.JavaCallableWrappers/​JavaCallableMethodClassifier.cs Removes the legacy classifier.
external/​Java.Interop/​src/​Java.Interop.Tools.JavaCallableWrappers/​Java.Interop.Tools.JavaCallableWrappers/​CallableWrapperWriterOptions.cs Removes obsolete writer options.
external/​Java.Interop/​src/​Java.Interop.Tools.JavaCallableWrappers/​Java.Interop.Tools.JavaCallableWrappers/​CallableWrapperReaderOptions.cs Removes obsolete reader options.
external/​Java.Interop/​src/​Java.Interop.Tools.JavaCallableWrappers/​Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/​CallableWrapperTypeAnnotation.cs Removes legacy annotation emission.
external/​Java.Interop/​src/​Java.Interop.Tools.JavaCallableWrappers/​Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/​CallableWrapperType.cs Removes the legacy wrapper model/writer.
external/​Java.Interop/​src/​Java.Interop.Tools.JavaCallableWrappers/​Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/​CallableWrapperMethod.cs Removes legacy method emission.
external/​Java.Interop/​src/​Java.Interop.Tools.JavaCallableWrappers/​Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/​CallableWrapperField.cs Removes legacy field emission.
external/​Java.Interop/​src/​Java.Interop.Tools.JavaCallableWrappers/​Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/​CallableWrapperConstructor.cs Removes legacy constructor emission.
external/​Java.Interop/​src/​Java.Interop.Tools.JavaCallableWrappers/​Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/​CallableWrapperApplicationConstructor.cs Removes legacy application constructors.
external/​Java.Interop/​src/​Java.Interop.Tools.JavaCallableWrappers/​Java.Interop.Tools.JavaCallableWrappers.Adapters/​XmlImporter.cs Removes the obsolete XML importer.
external/​Java.Interop/​src/​Java.Interop.Tools.JavaCallableWrappers/​Java.Interop.Tools.JavaCallableWrappers.Adapters/​XmlExporter.cs Removes the obsolete XML exporter.
external/​Java.Interop/​src/​Java.Interop.Tools.JavaCallableWrappers/​Java.Interop.Tools.JavaCallableWrappers.Adapters/​CecilImporter.cs Removes the obsolete Cecil adapter.
external/​Java.Interop/​src/​Java.Interop.Tools.JavaCallableWrappers/​Extensions/​XmlExtensions.cs Removes adapter-only XML helpers.
external/​Java.Interop/​src/​Java.Interop.Tools.Diagnostics/​Java.Interop.Tools.Diagnostics/​Diagnostic.cs Removes retired diagnostic references.
external/​Java.Interop/​src/​Java.Interop.Localization/​Resources.resx Removes retired emitter diagnostics.
external/​Java.Interop/​src/​Java.Interop.Localization/​Resources.Designer.cs Removes corresponding generated accessors.
external/​Java.Interop/​Java.Interop.slnx Removes jcw-gen.
external/​Java.Interop/​Directory.Build.targets Updates dependency-collision commentary.
Documentation/​guides/​internals/​JavaJNI_Interop.md Documents the supported pipeline and removals.
build-tools/​scripts/​Jar.targets Uses the retained runtime JAR for fixtures.
build-tools/​installers/​create-installers.targets Packages only retained runtime artifacts.
.github/​skills/​tests/​references/​test-catalog.md Reclassifies the remaining Java.Interop tests.
.github/​instructions/​java-interop.instructions.md Points JCW generation to the trimmable pipeline.
Files not reviewed (1)
  • external/Java.Interop/src/Java.Interop.Localization/Resources.Designer.cs: Generated file

🧠 Review effort: Balanced

Comment thread Documentation/guides/internals/JavaJNI_Interop.md
Remove exact retired JAR/DEX paths before Build and Clean even when
retained runtime generation is up to date.  Cover repeated seeded
upgrades, retained output timestamps, unrelated files and deletion
error propagation.  Remove the obsolete Kotlin XA4217 catalog entry
while retaining the active architecture diagnostic.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@simonrozsival simonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label Oct 12, 2026
Merge main at abe9f43.
Retain the intentional legacy JCW emitter, golden-test, and CLI
retirements when reconciling the single-style cleanup.  Preserve
upstream Throwable ownership, field retention, native bootstrap,
NDK tooling and R8 changes.

Validate retained utilities, Java/native table shapes, build/clean
contracts and refreshed native/managed SDK packaging together.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsival enabled auto-merge (squash) October 12, 2026 20:10
@simonrozsival

Copy link
Copy Markdown
Member Author

@dalexsoto review

@dalexsoto dalexsoto left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The complete 55-file source review and separate end-to-end integration/completeness pass found no high-confidence blocker. The authorized legacy tooling/bootstrap retirements are separated from retained utilities, supported XAJavaInterop1 binding generation and the current trimmable pipeline. Constructor/super sequencing, managed activation, nonempty callback/UCO tables, GC/reference edges, providers and both runtimes' retained configuration/R8 boundaries remain connected.

Both earlier concerns are fixed: the independent Build/Clean hook deletes exactly the eight retired artifact paths even on no-op builds and propagates deletion failures, while the obsolete Kotlin XA4217 index entry is removed without disturbing the active architecture diagnostic. The retained JAR/DEX, actual JNI-header producer, fixture and packaging consumers, resource/designer parity and upstream merge preservation are consistent. Intentional compatibility breaks and excluded follow-up candidates remain accepted scope. This is a static code-review approval, not reviewer execution of author receipts or completed CI; refreshed exact-head checks had no failures but some remained pending.

@simonrozsival
simonrozsival merged commit dad5d14 into main Oct 12, 2026
42 checks passed
@simonrozsival
simonrozsival deleted the simonrozsival-generated-java-cleanup-analysis branch October 12, 2026 22:42
simonrozsival added a commit that referenced this pull request Oct 13, 2026
Remove `Java.Interop.Tools.JavaCallableWrappers.JavaTypeScanner` now
that its last consumers were retired in [#13080](#13080)
and [#13094](#13094).  Also remove
`Java.Interop.Tools.JavaCallableWrappers.Utilities.CecilExtensions`:
its type-registration adapter was used only by the scanner, and its
method/export/source adapters lost their consumers with the old emitter.
This intentionally retires the public tooling scanner without a stub.

Keep the assembly, shared naming/hash/identifier utilities, modern
`JavaPeerScanner`, and all remaining tests unchanged.  Update only the
existing test-catalog descriptions that still advertised legacy scanning.
Binding-reference, tracked-source, linked-file, and configuration searches
found no live consumers.  Comparing the baseline and final implementation
and reference assemblies shows only the two intended type removals; the
other 29 top-level definitions have identical IL after normalizing address
layout.

**Validation:** the own-worktree Debug SDK build and explicit affected
builds passed.  Baseline/changed naming tests passed 18/18 and binding
generator tests passed 478/478.  Generator-helper tests passed 18/18,
SDK-backed modern typemap tests passed 34/34, and focused host integration
passed 24/24 across CoreCLR and NativeAOT.  Final runs have no failures or
skips, including all seven framework cases initially skipped before the
local SDK was prepared.  Device tests were not run: this removes unused
host tooling and does not change generated code or runtime paths.

<details>
<summary>Local validation commands and results</summary>

All commands ran in this worktree, on the committed change based on
`e03caec36337c9c5698cc60ca3e2ae50839636a5`.

| Command | Result |
| --- | --- |
| `dotnet build external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.csproj -c Debug -f netstandard2.0 -m:2 --disable-build-servers -v minimal` | Baseline and changed passed; 0 warnings/errors |
| `dotnet test external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers-Tests.csproj -c Debug -m:2 --disable-build-servers -v minimal` | Baseline and changed: 18 passed, 0 skipped |
| `dotnet test external/Java.Interop/tests/generator-Tests/generator-Tests.csproj -c Debug -m:2 --disable-build-servers -v minimal` | Baseline and changed: 478 passed, 0 skipped |
| `dotnet test external/Java.Interop/tests/Java.Interop.Tools.Generator-Tests/Java.Interop.Tools.Generator-Tests.csproj -c Debug -m:2 --disable-build-servers -v minimal` | 18 passed, 0 skipped |
| `dotnet build external/Java.Interop/tools/generator/generator.csproj -c Debug -f net10.0 -m:2 --disable-build-servers -v minimal` | Passed; 0 warnings/errors |
| `dotnet build external/Java.Interop/src/Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings.csproj -c Debug -f net10.0 -m:2 --disable-build-servers -v minimal` | Passed; 0 warnings/errors |
| `dotnet build src/Microsoft.Android.Sdk.TrimmableTypeMap/Microsoft.Android.Sdk.TrimmableTypeMap.csproj -c Debug -f net11.0 -m:2 --disable-build-servers -v minimal` | Passed; 0 warnings/errors |
| `make prepare CONFIGURATION=Debug MSBUILD_ARGS='-m:2 --disable-build-servers -nr:false'` | Passed; provisioned the repository-pinned local SDK |
| `make all CONFIGURATION=Debug MSBUILD_ARGS='-m:2 --disable-build-servers -nr:false -p:NinjaPath=/Users/simon/.copilot/session-state/2930120b-d71d-4dc9-b958-174c233d5b97/files/scanner-ninja-j2'` | Final full solution and local-workload build passed |
| `./dotnet-local.sh build Microsoft.Android.slnx -t:BuildExtraApiLevels -c Debug -m:2 --disable-build-servers -nr:false -p:NinjaPath=/Users/simon/.copilot/session-state/2930120b-d71d-4dc9-b958-174c233d5b97/files/scanner-ninja-j2 -bl:/Users/simon/.copilot/session-state/2930120b-d71d-4dc9-b958-174c233d5b97/files/scanner-sdk-extra-apis.binlog` | Passed; built the missing own API 37.1/37.2 reference outputs; 62 existing generated/API warnings |
| `./dotnet-local.sh build build-tools/create-packs/Microsoft.Android.Sdk.proj -t:ConfigureLocalWorkload -c Debug -m:2 --disable-build-servers -nr:false -v minimal` | Passed |
| `./dotnet-local.sh build src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj -c Debug -m:2 --disable-build-servers -nr:false -v minimal` | Passed at declared `netstandard2.0`, with own modern-framework dependencies; 30 existing warnings |
| `./dotnet-local.sh test src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/Microsoft.Android.Build.Tasks.Tests.csproj -c Debug -m:2 --disable-build-servers -nr:false -v minimal --filter 'FullyQualifiedName~GenerateTrimmableTypeMapTests\|FullyQualifiedName~TrimmableTypeMap' --logger 'trx;LogFileName=scanner-modern-framework.trx' --results-directory /Users/simon/.copilot/session-state/2930120b-d71d-4dc9-b958-174c233d5b97/files` | 34 passed, 0 skipped; all seven SDK-dependent cases passed |

The session-only Ninja wrapper executes the prepared real Ninja with
`-j2`, without changing shared tools or repository build files.

Focused host validation used the following selection:

	HOST_FILTER='FullyQualifiedName~BindingBuildTest.DotNetBuildBinding|FullyQualifiedName~BindingBuildTest.UnmanagedCallersOnlyCallbacks|FullyQualifiedName~BindingBuildTest.BindingLibraryIncremental|FullyQualifiedName~TrimmableTypeMapBuildTests.BindingCallbackFormatSupportsDefaultConsumer|FullyQualifiedName~TrimmableTypeMapBuildTests.Build_ImplicitConstructorUsesCompatibleBaseJniSignature|FullyQualifiedName~TrimmableTypeMapBuildTests.Build_ExplicitExportConstructorAttributeOrders_PreserveJniSignatures|FullyQualifiedName~TrimmableTypeMapBuildTests.Build_WithTrimmableTypeMap_AbstractTypeWithProtectedCtor_Succeeds|FullyQualifiedName~TrimmableTypeMapBuildTests.TrimmableTypeMap_PreservesJniOnlyConstructorThroughR8|FullyQualifiedName~TrimmableTypeMapBuildTests.TrimmableTypeMap_PackagesAndroidJavaProxyThrowable|FullyQualifiedName~TrimmableTypeMapBuildTests.RetainedTypeMapRulesDriveR8|FullyQualifiedName~TrimmableTypeMapBuildTests.TrimmableTypeMap_PreserveLists_ArePackagedInSdk|FullyQualifiedName~TrimmableTypeMapBuildTests.TrimmableTypeMap_ReferencePack_DoesNotShipLegacyPlatformJcws|FullyQualifiedName~TrimmableTypeMapBuildTests.TrimmableTypeMap_RuntimeArtifacts_ArePackagedInSdk|FullyQualifiedName~TrimmableTypeMapBuildTests.ReleaseCoreClrTrimmableTypeMap_RemovesUnreferencedBindingOutputs|FullyQualifiedName~TrimmableTypeMapBuildTests.Build_TrimmableTypeMap_UsesMonoAndroidImplementationMetadata'
	NUNIT_MSBUILD_ARGS=$'-m:2\n-nr:false\n-p:UseSharedCompilation=false' DOTNET_CLI_USE_MSBUILD_SERVER=0 ./dotnet-local.sh test bin/TestDebug/net10.0/Xamarin.Android.Build.Tests.dll --filter "$HOST_FILTER" --logger 'trx;LogFileName=scanner-host.trx' --results-directory /Users/simon/.copilot/session-state/2930120b-d71d-4dc9-b958-174c233d5b97/files -- NUnit.NumberOfTestWorkers=2

Result: **24 passed, 0 failed, 0 skipped** (7m27s).  This covers binding
incrementality, default callbacks, constructor signatures, JNI-only R8
retention, reference/runtime packaging, and removal of unused bindings.

Resolved preparation/invocation failures: the first cold solution
compile lacked generated `ANDROID_*` constants; an unchanged retry
imported the generated project items.  Local workload configuration needed
the existing `BuildExtraApiLevels` target before API 37.1/37.2 packs were
available.  Passing `-f netstandard2.0` to the task project leaked that
framework to its modern dependencies; using its declared framework fixed
the invocation.  The first host attempt put multiple response-file
arguments on one line; newline-separated arguments fixed it.  All retries
used unchanged sources, without pin or build-file workarounds.

</details>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants