Skip to content

Commit fb0ad74

Browse files
authored
Merge pull request #2 from andriydruk/master
Fix FindClass from attached to VM threads
2 parents 3a48760 + 9f7ae42 commit fb0ad74

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ import PackageDescription
1111
let package = Package(
1212
name: "java_swift",
1313
dependencies: [
14-
.Package(url: "https://github.com/SwiftJava/CJavaVM.git", versions: Version(1,0,0)..<Version(10,0,0)),
14+
.Package(url: "https://github.com/SwiftJava/CJavaVM.git", "1.1.3"),
1515
]
1616
)

Sources/JNICore.swift

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@ public func JNI_OnLoad( jvm: UnsafeMutablePointer<JavaVM?>, ptr: UnsafeRawPointe
2323
#if os(Android)
2424
DispatchQueue.setThreadDetachCallback( JNI_DetachCurrentThread )
2525
#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+
2637
return jint(JNI_VERSION_1_6)
2738
}
2839

@@ -39,6 +50,7 @@ open class JNICore {
3950

4051
open var jvm: UnsafeMutablePointer<JavaVM?>?
4152
open var api: JNINativeInterface_!
53+
open var classLoader: jclass!
4254

4355
open var envCache = [pthread_t:UnsafeMutablePointer<JNIEnv?>?]()
4456
fileprivate let envLock = NSLock()
@@ -165,11 +177,22 @@ open class JNICore {
165177
public func run() {
166178
RunLoop.main.run(until: Date.distantFuture)
167179
}
180+
181+
private var loadClassMethodID: jmethodID?
168182

169183
open func FindClass( _ name: UnsafePointer<Int8>, _ file: StaticString = #file, _ line: Int = #line ) -> jclass? {
170184
autoInit()
171185
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+
173196
if clazz == nil {
174197
report( "Could not find class \(String( cString: name ))", file, line )
175198
if strncmp( name, "org/swiftjava/", 14 ) == 0 {

0 commit comments

Comments
 (0)