@@ -23,6 +23,17 @@ public func JNI_OnLoad( jvm: UnsafeMutablePointer<JavaVM?>, ptr: UnsafeRawPointe
23
23
#if os(Android)
24
24
DispatchQueue . setThreadDetachCallback ( JNI_DetachCurrentThread )
25
25
#endif
26
+
27
+ // Save ContextClassLoader for FindClass usage
28
+ // When a thread is attached to the VM, the context class loader is the bootstrap loader.
29
+ // https://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/invocation.html
30
+ // https://developer.android.com/training/articles/perf-jni.html#faq_FindClass
31
+ let threadClass = JNI . api. FindClass ( env, " java/lang/Thread " )
32
+ let currentThreadMethodID = JNI . api. GetStaticMethodID ( env, threadClass, " currentThread " , " ()Ljava/lang/Thread; " )
33
+ let getContextClassLoaderMethodID = JNI . api. GetMethodID ( env, threadClass, " getContextClassLoader " , " ()Ljava/lang/ClassLoader; " )
34
+ let currentThread = JNI . api. CallStaticObjectMethodA ( env, threadClass, currentThreadMethodID, nil )
35
+ JNI . classLoader = JNI . api. NewGlobalRef ( env, JNI . api. CallObjectMethodA ( env, currentThread, getContextClassLoaderMethodID, nil ) )
36
+
26
37
return jint ( JNI_VERSION_1_6)
27
38
}
28
39
@@ -39,6 +50,7 @@ open class JNICore {
39
50
40
51
open var jvm : UnsafeMutablePointer < JavaVM ? > ?
41
52
open var api : JNINativeInterface_ !
53
+ open var classLoader : jclass !
42
54
43
55
open var envCache = [ pthread_t : UnsafeMutablePointer < JNIEnv ? > ? ] ( )
44
56
fileprivate let envLock = NSLock ( )
@@ -165,11 +177,22 @@ open class JNICore {
165
177
public func run( ) {
166
178
RunLoop . main. run ( until: Date . distantFuture)
167
179
}
180
+
181
+ private var loadClassMethodID : jmethodID ?
168
182
169
183
open func FindClass( _ name: UnsafePointer < Int8 > , _ file: StaticString = #file, _ line: Int = #line ) -> jclass ? {
170
184
autoInit ( )
171
185
ExceptionReset ( )
172
- let clazz : jclass ? = api. FindClass ( env, name )
186
+
187
+ var locals = [ jobject] ( )
188
+ var args = [ jvalue ( l: String ( cString: name) . localJavaObject ( & locals) ) ]
189
+ let clazz : jclass ? = JNIMethod . CallObjectMethod ( object: classLoader,
190
+ methodName: " loadClass " ,
191
+ methodSig: " (Ljava/lang/String;)Ljava/lang/Class; " ,
192
+ methodCache: & loadClassMethodID,
193
+ args: & args,
194
+ locals: & locals)
195
+
173
196
if clazz == nil {
174
197
report ( " Could not find class \( String ( cString: name ) ) " , file, line )
175
198
if strncmp ( name, " org/swiftjava/ " , 14 ) == 0 {
0 commit comments