Skip to content

Commit 6611420

Browse files
committed
Use Class.ForName(String, boolean, ClassLoader)
Context: dotnet/android#9931 Context: dotnet/android#9931 (comment) The attempted integration test crashed! F mono-rt : [ERROR] FATAL UNHANDLED EXCEPTION: Java.Lang.ClassNotFoundException: Didn't find class "crc641855b07eca6dcc03.MyCb" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/system/lib64, /system/product/lib64, /system/lib64, /system/product/lib64]] F mono-rt : at Java.Interop.JniEnvironment.Types.TryFindClass(String classname, Boolean throwOnError) F mono-rt : at Java.Interop.JniEnvironment.Types.FindClass(String classname) F mono-rt : at Java.Interop.JniType..ctor(String classname) F mono-rt : at Java.Interop.JniPeerMembers.JniInstanceMethods..ctor(Type declaringType) F mono-rt : at Java.Interop.JniPeerMembers.JniInstanceMethods.GetConstructorsForType(Type declaringType) F mono-rt : at Java.Interop.JniPeerMembers.JniInstanceMethods.StartCreateInstance(String constructorSignature, Type declaringType, JniArgumentValue* parameters) F mono-rt : at Java.Lang.Object..ctor() F mono-rt : at Java.InteropTests.MyCb..ctor() F mono-rt : at Java.InteropTests.JnienvTest.<>c__DisplayClass29_0.<DoNotLeakWeakReferences>b__1() F mono-rt : at System.Threading.Thread.StartHelper.Callback(Object state) F mono-rt : at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) F mono-rt : --- End of stack trace from previous location --- F mono-rt : at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) F mono-rt : --- End of managed Java.Lang.ClassNotFoundException stack trace --- F mono-rt : java.lang.ClassNotFoundException: Didn't find class "crc641855b07eca6dcc03.MyCb" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/system/lib64, /system/product/lib64, /system/lib64, /system/product/lib64]] F mono-rt : at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:196) F mono-rt : at java.lang.ClassLoader.loadClass(ClassLoader.java:379) F mono-rt : at java.lang.ClassLoader.loadClass(ClassLoader.java:312) Perhaps unsurprisingly, we need to provide the system ClassLoader in order to load types from outside the default "classpath", which is why we used `ClassLoader.loadClass()` in the first place. Instead of `Class.forName()`, use the [`Class.forName(String name, boolean initialize, ClassLoader loader)`][0] overload, so that we can provide a `ClassLoader` instance. This *should* fix the crash. [0]: https://developer.android.com/reference/java/lang/Class#forName(java.lang.String,%20boolean,%20java.lang.ClassLoader)
1 parent b8e729f commit 6611420

File tree

2 files changed

+16
-4
lines changed

2 files changed

+16
-4
lines changed

src/Java.Interop/Java.Interop/JniEnvironment.Types.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ static Types ()
3232
using (var t = new JniType ("java/lang/Class")) {
3333
Class_reference = t.PeerReference.NewGlobalRef ();
3434
Class_getName = t.GetInstanceMethod ("getName", "()Ljava/lang/String;");
35-
Class_forName = t.GetStaticMethod ("forName", "(Ljava/lang/String;)Ljava/lang/Class;");
35+
Class_forName = t.GetStaticMethod ("forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;");
3636
}
3737
}
3838

@@ -63,8 +63,10 @@ static unsafe JniObjectReference TryFindClass (string classname, bool throwOnErr
6363

6464
if (Class_forName.IsValid) {
6565
var java = info.ToJavaName (classname);
66-
var __args = stackalloc JniArgumentValue [1];
66+
var __args = stackalloc JniArgumentValue [3];
6767
__args [0] = new JniArgumentValue (java);
68+
__args [1] = new JniArgumentValue (true); // initialize the class
69+
__args [2] = new JniArgumentValue (info.Runtime.ClassLoader);
6870

6971
c = RawCallStaticObjectMethodA (info.EnvironmentPointer, out thrown, Class_reference.Handle, Class_forName.ID, (IntPtr) __args);
7072
JniObjectReference.Dispose (ref java);

src/Java.Interop/Java.Interop/JniRuntime.cs

+12-2
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ public partial class CreationOptions {
5858
public IntPtr InvocationPointer {get; set;}
5959
public IntPtr EnvironmentPointer {get; set;}
6060

61-
[Obsolete ("No longer supported; Class.forName() is now used instead")]
6261
public JniObjectReference ClassLoader {get; set;}
6362
[Obsolete ("No longer supported; Class.forName() is now used instead")]
6463
public IntPtr ClassLoader_LoadClass_id {get; set;}
@@ -154,7 +153,6 @@ public static void SetCurrent (JniRuntime newCurrent)
154153
bool DestroyRuntimeOnDispose;
155154

156155
internal JniObjectReference ClassLoader;
157-
internal JniMethodInfo? ClassLoader_LoadClass;
158156

159157
public IntPtr InvocationPointer {get; private set;}
160158

@@ -207,6 +205,18 @@ protected JniRuntime (CreationOptions options)
207205
var env = new JniEnvironmentInfo (envp, this);
208206
JniEnvironment.SetEnvironmentInfo (env);
209207

208+
ClassLoader = options.ClassLoader;
209+
if (ClassLoader.IsValid) {
210+
ClassLoader = ClassLoader.NewGlobalRef ();
211+
} else {
212+
using (var t = new JniType ("java/lang/ClassLoader")) {
213+
var m = t.GetStaticMethod ("getSystemClassLoader", "()Ljava/lang/ClassLoader;");
214+
var loader = JniEnvironment.StaticMethods.CallStaticObjectMethod (t.PeerReference, m);
215+
ClassLoader = loader.NewGlobalRef ();
216+
JniObjectReference.Dispose (ref loader);
217+
}
218+
}
219+
210220
#if !XA_JI_EXCLUDE
211221
ManagedPeer.Init ();
212222
#endif // !XA_JI_EXCLUDE

0 commit comments

Comments
 (0)