Skip to content

Commit f800c1a

Browse files
[Mono.Android] Java.Lang.Object.GetObject<T>() implementation (#9728)
Context: #9630 Context: #9716 Context: dotnet/java-interop@e288589 @jonathanpeppers attempted to prototype MAUI startup in a NativeAOT environment, which promptly crashes similar to: E AndroidRuntime: net.dot.jni.internal.JavaProxyThrowable: System.DllNotFoundException: DllNotFound_Linux, xa-internal-api, E AndroidRuntime: dlopen failed: library "xa-internal-api" not found E AndroidRuntime: dlopen failed: library "libxa-internal-api" not found E AndroidRuntime: E AndroidRuntime: at System.Runtime.InteropServices.NativeLibrary.LoadLibErrorTracker.Throw(String) + 0x47 E AndroidRuntime: at Internal.Runtime.CompilerHelpers.InteropHelpers.FixupModuleCell(InteropHelpers.ModuleFixupCell*) + 0xe2 E AndroidRuntime: at Internal.Runtime.CompilerHelpers.InteropHelpers.ResolvePInvokeSlow(InteropHelpers.MethodFixupCell*) + 0x35 E AndroidRuntime: at Android.Runtime.RuntimeNativeMethods.monodroid_TypeManager_get_java_class_name(IntPtr) + 0x22 E AndroidRuntime: at Java.Interop.TypeManager.GetClassName(IntPtr) + 0xe E AndroidRuntime: at Java.Interop.TypeManager.CreateInstance(IntPtr, JniHandleOwnership, Type) + 0x69 E AndroidRuntime: at Java.Lang.Object._GetObject[T](IntPtr, JniHandleOwnership) + 0x4e E AndroidRuntime: at Android.App.Application.n_OnCreate(IntPtr jnienv, IntPtr native__this) + 0x89 E AndroidRuntime: at my.MainApplication.n_onCreate(Native Method) E AndroidRuntime: at my.MainApplication.onCreate(MainApplication.java:24) E AndroidRuntime: at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1182) E AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6460) E AndroidRuntime: at android.app.ActivityThread.access$1300(ActivityThread.java:219) E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1859) E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:107) E AndroidRuntime: at android.os.Looper.loop(Looper.java:214) E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:7356) E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) because: 1. MAUI apps provide an `Android.App.Application` sublass, and 2. [`Application` is "special"][0], and 3. When `Java.Lang.Object.GetObject<T>()` is hit for an instance which doesn't already have an instance mapping -- i.e. `Object.PeekObject()` returns `null` -- then we'd hit `TypeManager.CreateInstance()`, which is a codepath full of P/Invokes, and P/Invokes don't currently work on NativeAOT [^1]. The solution is to partially resuscitate PR #9630, but this time have `Java.Lang.Object.GetObject<T>()` call `Java.Interop.JniRuntime.JniValueManager.GetPeer()` instead of `Java.Interop.JniRuntime.JniValueManager.GetValue()`; see also dotnet/java-interop@e288589d. This allows `Application` subclasses to be used (along with other build system changes present in #9716). This also cleans up a few things if `Java.Lang.Object` introduces an internal `DynamicallyAccessedMemberTypes Constructors` field. [0]: https://learn.microsoft.com/en-us/previous-versions/xamarin/android/internals/architecture#java-activation [^1]: It's *not* that NativeAOT doesn't support P/Invokes; it does. The problem is that for a P/Invoke to work, we need to know the name of the native library we're P/Invoking into, and our NativeAOT sample environment doesn't include any `.so` files other than the one for the app, i.e. whatever we'd P/Invoke into doesn't exist.
1 parent 3856e62 commit f800c1a

File tree

16 files changed

+40
-34
lines changed

16 files changed

+40
-34
lines changed

src/Mono.Android/Android.App/Activity.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ namespace Android.App {
66

77
partial class Activity {
88

9-
internal const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
10-
119
public T? FindViewById<
1210
[DynamicallyAccessedMembers (Constructors)]
1311
T

src/Mono.Android/Android.App/Dialog.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ protected Dialog (Android.Content.Context context, bool cancelable, EventHandler
1010
: this (context, cancelable, new Android.Content.IDialogInterfaceOnCancelListenerImplementor () { Handler = cancelHandler }) {}
1111

1212
public T? FindViewById<
13-
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
13+
[DynamicallyAccessedMembers (Constructors)]
1414
T
1515
> (int id)
1616
where T : Android.Views.View

src/Mono.Android/Android.App/FragmentManager.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
#if ANDROID_11
66
namespace Android.App {
77
public partial class FragmentManager {
8-
const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
9-
108
public T? FindFragmentById<
119
[DynamicallyAccessedMembers (Constructors)]
1210
T

src/Mono.Android/Android.OS/AsyncTask.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ public abstract class AsyncTask<
1818
TResult
1919
> : AsyncTask {
2020

21-
const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
22-
2321
static IntPtr java_class_handle;
2422
internal static IntPtr class_ref {
2523
get {

src/Mono.Android/Android.Runtime/JNIEnv.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,13 @@ public static void CopyArray (IntPtr src, string[] dest)
662662
AssertIsJavaObject (type);
663663

664664
IntPtr elem = GetObjectArrayElement (source, index);
665-
return Java.Lang.Object.GetObject (elem, JniHandleOwnership.TransferLocalRef, type);
665+
return GetObject (elem, type);
666+
667+
// FIXME: Since a Dictionary<Type, Func> is used here, the trimmer will not be able to properly analyze `Type t`
668+
// error IL2111: Method 'lambda expression' with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method.
669+
[UnconditionalSuppressMessage ("Trimming", "IL2067", Justification = "FIXME: https://github.com/xamarin/xamarin-android/issues/8724")]
670+
static object? GetObject (IntPtr e, Type t) =>
671+
Java.Lang.Object.GetObject (e, JniHandleOwnership.TransferLocalRef, t);
666672
} },
667673
{ typeof (Array), (type, source, index) => {
668674
IntPtr elem = GetObjectArrayElement (source, index);

src/Mono.Android/Android.Runtime/JavaArray.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4-
4+
using System.Diagnostics.CodeAnalysis;
55

66
namespace Android.Runtime {
77

88
[Register ("mono/android/runtime/JavaArray", DoNotGenerateAcw=true)]
9-
public sealed class JavaArray<T> : Java.Lang.Object, IList<T> {
9+
public sealed class JavaArray<
10+
[DynamicallyAccessedMembers (Constructors)]
11+
T
12+
> : Java.Lang.Object, IList<T> {
1013

1114
public JavaArray (IntPtr handle, JniHandleOwnership transfer)
1215
: base (handle, transfer)

src/Mono.Android/Android.Runtime/JavaCollection.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ namespace Android.Runtime {
1414
// java.util.Collection allows null values
1515
public class JavaCollection : Java.Lang.Object, System.Collections.ICollection {
1616

17-
internal const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
18-
1917
internal static IntPtr collection_class = JNIEnv.FindClass ("java/util/Collection");
2018

2119
internal static IntPtr id_add;

src/Mono.Android/Android.Runtime/JavaDictionary.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ namespace Android.Runtime {
1212
// java.util.HashMap allows null keys and values
1313
public class JavaDictionary : Java.Lang.Object, System.Collections.IDictionary {
1414

15-
internal const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
16-
1715
class DictionaryEnumerator : IDictionaryEnumerator {
1816

1917
IEnumerator simple_enumerator;

src/Mono.Android/Android.Runtime/JavaList.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ namespace Android.Runtime {
1010
// java.util.ArrayList allows null values
1111
public partial class JavaList : Java.Lang.Object, System.Collections.IList {
1212

13-
internal const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
1413
internal static readonly JniPeerMembers list_members = new XAPeerMembers ("java/util/List", typeof (JavaList), isInterface: true);
1514

1615
//

src/Mono.Android/Android.Runtime/JavaSet.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ public static IntPtr ToLocalJniHandle (ICollection? items)
269269
[Register ("java/util/HashSet", DoNotGenerateAcw=true)]
270270
// java.util.HashSet allows null
271271
public class JavaSet<
272-
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
272+
[DynamicallyAccessedMembers (Constructors)]
273273
T
274274
> : JavaSet, ICollection<T> {
275275

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy