Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0021abf
[TrimmableTypeMap] CoreCLR JavaMarshal value-manager split + JI bump
simonrozsival Jun 29, 2026
1a8254d
Remove AndroidReflectionJniValueManager (superseded by CoreCLR split …
simonrozsival Jun 29, 2026
0bad754
Address build failures
simonrozsival Jun 29, 2026
e06209e
Address warnings by enabling nullable
simonrozsival Jun 29, 2026
05da23c
Update acceptable breaking changes
simonrozsival Jun 29, 2026
094788d
Update acceptable breakages
simonrozsival Jun 29, 2026
85a605f
Suppress more warnings
simonrozsival Jun 29, 2026
c32c5f0
[NativeAOT] Use CoreClrJavaMarshalValueManager for default value manager
simonrozsival Jun 29, 2026
052ae81
[Mono.Android] Resolve derived interface peers in CoreClrJavaMarshalV…
simonrozsival Jun 29, 2026
f677d45
[Mono.Android] Share Java interface-hierarchy walk between value/type…
simonrozsival Jun 29, 2026
ba5a7ae
[Tests] Update NativeAOT BuildHasNoWarnings baseline 10 -> 6
simonrozsival Jun 29, 2026
46311a5
[Tests] Update BuildReleaseArm64 SimpleDotNet apkdesc size baselines
simonrozsival Jun 29, 2026
41c1bcc
[Mono.Android] Add JavaInterfaceHierarchy.cs to the compile list
simonrozsival Jun 29, 2026
f671457
Merge remote-tracking branch 'origin/main' into dev/simonrozsival/tri…
simonrozsival Jun 30, 2026
37f998a
Change name back to JavaMarshalValueManager
simonrozsival Jun 30, 2026
c684eee
Minimize PR: drop interface-resolution sub-feature, restore Trimmable…
simonrozsival Jun 30, 2026
73002ab
Undo unnecessary changes
simonrozsival Jun 30, 2026
0d3b069
Renive AndroidReflectionJniValueManager (again?)
simonrozsival Jun 30, 2026
ea2f9df
Remove unnecessary changes from JavaMarshalValueManager
simonrozsival Jun 30, 2026
8873f1c
Undo a few more changes
simonrozsival Jun 30, 2026
6cb72ae
Bring back ActivatePeer method
simonrozsival Jun 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ static NativeAotRuntimeOptions CreateJreVM (NativeAotRuntimeOptions builder)
builder.TypeManager ??= CreateDefaultTypeManager ();
#endif // NET

builder.ValueManager ??= new JavaMarshalValueManager ();
builder.ValueManager ??= CreateDefaultValueManager ();
builder.ObjectReferenceManager ??= new Android.Runtime.AndroidObjectReferenceManager ();

if (builder.InvocationPointer != IntPtr.Zero || builder.EnvironmentPointer != IntPtr.Zero)
Expand All @@ -84,6 +84,13 @@ static JniRuntime.JniTypeManager CreateDefaultTypeManager ()
return new ManagedTypeManager ();
}

[UnconditionalSuppressMessage ("Trimming", "IL2026", Justification = "CoreCLR value manager is preserved by the MarkJavaObjects trimmer step.")]
[UnconditionalSuppressMessage ("Trimming", "IL3050", Justification = "This value manager won't be used in Native AOT builds in the future.")]
static JniRuntime.JniValueManager CreateDefaultValueManager ()
{
return new JavaMarshalValueManager ();
}

public override string? GetCurrentManagedThreadName ()
{
return Thread.CurrentThread.Name;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#nullable disable
#nullable enable

using System;

Expand Down
7 changes: 1 addition & 6 deletions src/Mono.Android/Android.Graphics/Color.cs
Original file line number Diff line number Diff line change
Expand Up @@ -434,18 +434,13 @@ public static void RGBToHSV (int red, int green, int blue, float[] hsv)

public class ColorValueMarshaler : JniValueMarshaler<Color>
{
const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
const string ExpressionRequiresUnreferencedCode = "System.Linq.Expression usage may trim away required code.";

public override Type MarshalType {
get { return typeof (int); }
}

public override Color CreateGenericValue (
ref JniObjectReference reference,
JniObjectReferenceOptions options,
[DynamicallyAccessedMembers (Constructors)]
Type targetType)
public override Color CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type targetType)
{
throw new NotImplementedException ();
}
Expand Down
17 changes: 4 additions & 13 deletions src/Mono.Android/Android.Runtime/AndroidRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -314,11 +314,6 @@ public override void DeleteWeakGlobalReference (ref JniObjectReference value)
class AndroidTypeManager : JniRuntime.ReflectionJniTypeManager {
bool jniAddNativeMethodRegistrationAttributePresent;

const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
const DynamicallyAccessedMemberTypes Methods = DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods;
const DynamicallyAccessedMemberTypes MethodsAndPrivateNested = Methods | DynamicallyAccessedMemberTypes.NonPublicNestedTypes;
const DynamicallyAccessedMemberTypes MethodsConstructors = MethodsAndPrivateNested | Constructors;

public AndroidTypeManager (bool jniAddNativeMethodRegistrationAttributePresent)
{
this.jniAddNativeMethodRegistrationAttributePresent = jniAddNativeMethodRegistrationAttributePresent;
Expand All @@ -335,7 +330,6 @@ protected override IEnumerable<Type> GetTypesForSimpleReference (string jniSimpl
}

[UnconditionalSuppressMessage ("Trimming", "IL2073", Justification = "Temporary suppression until legacy typemap entries carry DAM annotations.")]
[return: DynamicallyAccessedMembers (MethodsConstructors)]
protected override Type? GetTypeForSimpleReference (string jniSimpleReference)
{
var type = base.GetTypeForSimpleReference (jniSimpleReference);
Expand Down Expand Up @@ -384,10 +378,7 @@ protected override IEnumerable<string> GetSimpleReferences (Type type)
return JniRemappingLookup.GetReplacementMethodInfo (jniSourceType, jniMethodName, jniMethodSignature);
}

[return: DynamicallyAccessedMembers (Constructors)]
protected override Type? GetInvokerTypeCore (
[DynamicallyAccessedMembers (Constructors)]
Type type)
protected override Type? GetInvokerTypeCore (Type type)
{
if (type.IsInterface || type.IsAbstract) {
return JavaObjectExtensions.GetInvokerType (type)
Expand Down Expand Up @@ -500,17 +491,17 @@ static bool CallRegisterMethodByIndex (JniNativeMethodRegistrationArguments argu
[Obsolete ("Use RegisterNativeMembers(JniType, Type, ReadOnlySpan<char>) instead.")]
public override void RegisterNativeMembers (
JniType nativeClass,
[DynamicallyAccessedMembers (MethodsAndPrivateNested)]
Type type,
string? methods) =>
RegisterNativeMembers (nativeClass, type, methods.AsSpan ());

[UnconditionalSuppressMessage ("Trimming", "IL2057", Justification = "Type.GetType() can never statically know the string value parsed from parameter 'methods'.")]
[UnconditionalSuppressMessage ("Trimming", "IL2067", Justification = "Delegate.CreateDelegate() can never statically know the string value parsed from parameter 'methods'.")]
[UnconditionalSuppressMessage ("Trimming", "IL2070", Justification = "GetMethods can never statically know the string value parsed from parameter 'methods'.")]
[UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = "Delegate.CreateDelegate() can never statically know the string value parsed from parameter 'methods'.")]
public override void RegisterNativeMembers (
JniType nativeClass,
[DynamicallyAccessedMembers (MethodsAndPrivateNested)] Type type,
Type type,
ReadOnlySpan<char> methods)
{
try {
Expand Down Expand Up @@ -852,7 +843,7 @@ internal void RemovePeer (IJavaPeerable value, IntPtr hash)

public override void ActivatePeer (
JniObjectReference reference,
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type type,
Type type,
ConstructorInfo cinfo,
object?[]? argumentValues)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,13 @@
namespace Android.Runtime
{
sealed class IJavaObjectValueMarshaler : JniValueMarshaler<IJavaObject> {

const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
const string ExpressionRequiresUnreferencedCode = "System.Linq.Expression usage may trim away required code.";

internal static IJavaObjectValueMarshaler Instance = new IJavaObjectValueMarshaler ();

public override IJavaObject CreateGenericValue (
ref JniObjectReference reference,
JniObjectReferenceOptions options,
[DynamicallyAccessedMembers (Constructors)]
Type? targetType)
{
throw new NotImplementedException ();
Expand Down
11 changes: 9 additions & 2 deletions src/Mono.Android/Android.Runtime/JNIEnvInit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,21 @@ internal static JniRuntime.JniValueManager CreateValueManager ()
}

if (RuntimeFeature.IsCoreClrRuntime) {
return new JavaMarshalValueManager ();
return CreateJavaMarshalValueManager ();
}

if (RuntimeFeature.IsNativeAotRuntime) {
return new JavaMarshalValueManager ();
return CreateJavaMarshalValueManager ();
}

throw new NotSupportedException ("Internal error: unknown runtime not supported");

[UnconditionalSuppressMessage ("Trimming", "IL2026", Justification = "CoreCLR value manager is preserved by the MarkJavaObjects trimmer step.")]
[UnconditionalSuppressMessage ("Trimming", "IL3050", Justification = "This value manager won't be used in Native AOT builds in the future.")]
JniRuntime.JniValueManager CreateJavaMarshalValueManager ()
{
return new JavaMarshalValueManager ();
}
}

static void InitializeCommonState (JnienvInitializeArgs args)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,20 @@

namespace Microsoft.Android.Runtime;

class JavaMarshalValueManager : AndroidReflectionJniValueManager
[RequiresDynamicCode ("This value manager is reflection-backed and can break in AOT scenarios.")]
[RequiresUnreferencedCode ("This value manager is reflection-backed and relies on custom trimming rules.")]
sealed class JavaMarshalValueManager : JniRuntime.ReflectionJniValueManager
{
const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
const BindingFlags ActivationConstructorBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;

static readonly Type[] XAConstructorSignature = new Type [] { typeof (IntPtr), typeof (JniHandleOwnership) };

bool disposed;

public JavaMarshalValueManager ()
{
JavaMarshalRegisteredPeers.InitializeIfNeeded ();
}

protected override void Dispose (bool disposing)
{
disposed = true;
base.Dispose (disposing);
}

void ThrowIfDisposed ()
{
if (disposed)
throw new ObjectDisposedException (nameof (JavaMarshalValueManager));
}

public override void WaitForGCBridgeProcessing ()
{
// Intentionally empty. The Mono runtime's own implementation acknowledges this
Expand Down Expand Up @@ -68,7 +56,7 @@ public override void FinalizePeer (IJavaPeerable value)
JavaMarshalRegisteredPeers.FinalizePeer (value);
}

public override void ActivatePeer (JniObjectReference reference, [DynamicallyAccessedMembers (Constructors)] Type type, ConstructorInfo cinfo, object?[]? argumentValues)
public override void ActivatePeer (JniObjectReference reference, Type type, ConstructorInfo cinfo, object?[]? argumentValues)
{
if (RuntimeFeature.TrimmableTypeMap)
throw new PlatformNotSupportedException ("Activating Java peers is not supported when TrimmableTypeMap is enabled.");
Expand All @@ -87,7 +75,7 @@ public override List<JniSurfacedPeerInfo> GetSurfacedPeers ()
[DynamicallyAccessedMembers (Constructors)]
Type? targetType)
{
ThrowIfDisposed ();
EnsureNotDisposed ();

if (!reference.IsValid) {
return null;
Expand Down
Loading
Loading