From 26e30771d2327e367ff46b58c27273e5a3890534 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Tue, 16 Jun 2026 11:51:32 +0200 Subject: [PATCH 1/3] [Mono.Android] Remove dead Java.Interop.__TypeRegistrations plumbing The binding generator used to emit a `Java.Interop.__TypeRegistrations` class whose `RegisterPackages ()` populated `TypeManager.packageLookup`. The only reader of that dictionary -- the `TypeRegistrationFallback` path in `GetJavaToManagedTypeCore` -- was removed in #9471, so the dictionary has been write-only (and, since nothing generated calls it, effectively unused) ever since. Type resolution now goes through the native / trimmable type map. This bumps external/Java.Interop to the generator change that stops emitting the dead class (dotnet/java-interop#1470) and removes the now-dead runtime plumbing: * Delete the `packageLookup` field and `LazyInitPackageLookup ()`. * `TypeManager.RegisterPackage`/`RegisterPackages` are shipped public API, so they are kept as validated no-op stubs rather than removed. Fixes #11663 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- external/Java.Interop | 2 +- src/Mono.Android/Java.Interop/TypeManager.cs | 42 +++++--------------- 2 files changed, 10 insertions(+), 34 deletions(-) diff --git a/external/Java.Interop b/external/Java.Interop index b881d21f51c..3b78d377457 160000 --- a/external/Java.Interop +++ b/external/Java.Interop @@ -1 +1 @@ -Subproject commit b881d21f51cbac6e175de1b2f6c254fe3846aa1d +Subproject commit 3b78d377457ac90cb19522658fb8ce91a5e99f7c diff --git a/src/Mono.Android/Java.Interop/TypeManager.cs b/src/Mono.Android/Java.Interop/TypeManager.cs index cc0b22936bd..4d2dae08ea7 100644 --- a/src/Mono.Android/Java.Interop/TypeManager.cs +++ b/src/Mono.Android/Java.Interop/TypeManager.cs @@ -453,47 +453,23 @@ public static void RegisterType (string java_class, Type t) } } - static Dictionary>>? packageLookup; - - [MemberNotNull (nameof (packageLookup))] - static void LazyInitPackageLookup () - { - if (packageLookup == null) - packageLookup = new Dictionary>> (StringComparer.Ordinal); - } - + // The package-based Java-to-managed type registration fallback was removed + // (https://github.com/dotnet/android/issues/11663); type resolution now goes + // through the native / trimmable type map, and the generator no longer emits + // the `Java.Interop.__TypeRegistrations` class that called these methods. They + // are retained for API compatibility but no longer register anything. public static void RegisterPackage (string package, Converter lookup) { - LazyInitPackageLookup (); - - lock (packageLookup!) { - if (!packageLookup.TryGetValue (package, out var lookups)) - packageLookup.Add (package, lookups = new List> ()); - lookups.Add (lookup); - } + ArgumentNullException.ThrowIfNull (package); + ArgumentNullException.ThrowIfNull (lookup); } public static void RegisterPackages (string[] packages, Converter[] lookups) { - LazyInitPackageLookup (); - - if (packages == null) - throw new ArgumentNullException ("packages"); - if (lookups == null) - throw new ArgumentNullException ("lookups"); + ArgumentNullException.ThrowIfNull (packages); + ArgumentNullException.ThrowIfNull (lookups); if (packages.Length != lookups.Length) throw new ArgumentException ("`packages` and `lookups` arrays must have same number of elements."); - - lock (packageLookup!) { - for (int i = 0; i < packages.Length; ++i) { - string package = packages [i]; - var lookup = lookups [i]; - - if (!packageLookup.TryGetValue (package, out var _lookups)) - packageLookup.Add (package, _lookups = new List> ()); - _lookups.Add (lookup); - } - } } [Register ("mono/android/TypeManager", DoNotGenerateAcw = true)] From e7eaaf478cbabdc0bddf9fafd01214e83c255ea3 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Tue, 16 Jun 2026 11:57:04 +0200 Subject: [PATCH 2/3] [Mono.Android] Throw NotSupportedException with an explanatory message `TypeManager.RegisterPackage`/`RegisterPackages` are retired shipped public APIs whose registration mechanism no longer exists. Rather than silently doing nothing, they now throw `NotSupportedException` carrying an explanation of why the call is unsupported and what replaced it ("Java package type registration is no longer supported. Java-to-managed type resolution now goes through the native and trimmable type maps."), so a caller that still invokes them gets a clear, actionable reason instead of a bare exception. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/Mono.Android/Java.Interop/TypeManager.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Mono.Android/Java.Interop/TypeManager.cs b/src/Mono.Android/Java.Interop/TypeManager.cs index 4d2dae08ea7..b00ea6056b0 100644 --- a/src/Mono.Android/Java.Interop/TypeManager.cs +++ b/src/Mono.Android/Java.Interop/TypeManager.cs @@ -453,23 +453,23 @@ public static void RegisterType (string java_class, Type t) } } + const string TypeRegistrationNotSupported = + "Java package type registration is no longer supported. Java-to-managed type resolution now goes through the native and trimmable type maps."; + // The package-based Java-to-managed type registration fallback was removed // (https://github.com/dotnet/android/issues/11663); type resolution now goes // through the native / trimmable type map, and the generator no longer emits - // the `Java.Interop.__TypeRegistrations` class that called these methods. They - // are retained for API compatibility but no longer register anything. + // the `Java.Interop.__TypeRegistrations` class that called these methods. These + // shipped public APIs are retained for binary compatibility but now throw, as + // they can no longer register anything. public static void RegisterPackage (string package, Converter lookup) { - ArgumentNullException.ThrowIfNull (package); - ArgumentNullException.ThrowIfNull (lookup); + throw new NotSupportedException (TypeRegistrationNotSupported); } public static void RegisterPackages (string[] packages, Converter[] lookups) { - ArgumentNullException.ThrowIfNull (packages); - ArgumentNullException.ThrowIfNull (lookups); - if (packages.Length != lookups.Length) - throw new ArgumentException ("`packages` and `lookups` arrays must have same number of elements."); + throw new NotSupportedException (TypeRegistrationNotSupported); } [Register ("mono/android/TypeManager", DoNotGenerateAcw = true)] From 4b19fba725113e4e7e1cc818348757844e1ca61d Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Tue, 16 Jun 2026 13:14:08 +0200 Subject: [PATCH 3/3] [Mono.Android] Don't bump external/Java.Interop in this PR Revert the external/Java.Interop submodule bump. Pinning an unmerged java-interop PR-branch commit is fragile, and advancing to java-interop main HEAD would drag in unrelated changes (e.g. dotnet/java-interop#1441) that need their own coordination. The generator-side removal lives in dotnet/java-interop#1470 and will reach Mono.Android through the normal submodule bump once it merges; this PR keeps only the independent runtime cleanup of the now-dead `packageLookup` plumbing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- external/Java.Interop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/Java.Interop b/external/Java.Interop index 3b78d377457..b881d21f51c 160000 --- a/external/Java.Interop +++ b/external/Java.Interop @@ -1 +1 @@ -Subproject commit 3b78d377457ac90cb19522658fb8ce91a5e99f7c +Subproject commit b881d21f51cbac6e175de1b2f6c254fe3846aa1d