@@ -19,10 +19,9 @@ public func JNI_OnLoad( jvm: UnsafeMutablePointer<JavaVM?>, ptr: UnsafeRawPointe
19
19
JNI . jvm = jvm
20
20
let env : UnsafeMutablePointer < JNIEnv ? > ? = JNI . GetEnv ( )
21
21
JNI . api = env!. pointee!. pointee
22
- JNI . envCache [ JNI . threadKey] = env
23
- #if os(Android)
24
- DispatchQueue . setThreadDetachCallback ( JNI_DetachCurrentThread )
25
- #endif
22
+ if pthread_setspecific ( JNICore . envVarKey, env ) != 0 {
23
+ JNI . report ( " Could not set pthread specific GetEnv() " )
24
+ }
26
25
27
26
// Save ContextClassLoader for FindClass usage
28
27
// When a thread is attached to the VM, the context class loader is the bootstrap loader.
@@ -35,9 +34,6 @@ public func JNI_OnLoad( jvm: UnsafeMutablePointer<JavaVM?>, ptr: UnsafeRawPointe
35
34
36
35
public func JNI_DetachCurrentThread( ) {
37
36
_ = JNI . jvm? . pointee? . pointee. DetachCurrentThread ( JNI . jvm )
38
- JNI . envLock. lock ( )
39
- JNI . envCache [ JNI . threadKey] = nil
40
- JNI . envLock. unlock ( )
41
37
}
42
38
43
39
public let JNI = JNICore ( )
@@ -48,21 +44,25 @@ open class JNICore {
48
44
open var api : JNINativeInterface_ !
49
45
open var classLoader : jobject ?
50
46
51
- open var envCache = [ pthread_t : UnsafeMutablePointer < JNIEnv ? > ? ] ( )
52
- fileprivate let envLock = NSLock ( )
53
-
54
- open var threadKey : pthread_t { return pthread_self ( ) }
47
+ static var envVarKey : pthread_key_t = {
48
+ var envVarKey : pthread_key_t = 0
49
+ if pthread_key_create ( & envVarKey, { _ in
50
+ _ = JNI . jvm? . pointee? . pointee. DetachCurrentThread ( JNI . jvm )
51
+ } ) != 0 {
52
+ JNI . report ( " Could not create pthread envVarKey " )
53
+ }
54
+ return envVarKey
55
+ } ( )
55
56
56
57
open var env : UnsafeMutablePointer < JNIEnv ? > ? {
57
- let currentThread = threadKey
58
- if let env = envCache [ currentThread] {
59
- return env
58
+ if let existing = pthread_getspecific ( JNICore . envVarKey ) {
59
+ return existing. assumingMemoryBound ( to: JNIEnv ? . self)
60
60
}
61
61
62
62
let env = AttachCurrentThread ( )
63
- envLock . lock ( )
64
- envCache [ currentThread ] = env
65
- envLock . unlock ( )
63
+ if pthread_setspecific ( JNICore . envVarKey , env ) != 0 {
64
+ JNI . report ( " Could not set pthread specific env" )
65
+ }
66
66
return env
67
67
}
68
68
@@ -130,7 +130,9 @@ open class JNICore {
130
130
return false
131
131
}
132
132
133
- self . envCache [ threadKey] = tenv
133
+ if pthread_setspecific ( JNICore . envVarKey, tenv ) != 0 {
134
+ JNI . report ( " Could not set pthread specific tenv " )
135
+ }
134
136
self . api = self . env!. pointee!. pointee
135
137
return true
136
138
}
@@ -148,19 +150,21 @@ open class JNICore {
148
150
open func GetEnv( ) -> UnsafeMutablePointer < JNIEnv ? > ? {
149
151
var tenv : UnsafeMutablePointer < JNIEnv ? > ?
150
152
if withPointerToRawPointer ( to: & tenv, {
151
- JNI . jvm? . pointee? . pointee. GetEnv ( JNI . jvm, $0, jint ( JNI_VERSION_1_6) )
153
+ JNI . jvm? . pointee? . pointee. GetEnv ( JNI . jvm, $0, jint ( JNI_VERSION_1_6 ) )
152
154
} ) != jint ( JNI_OK) {
153
155
report ( " Unable to get initial JNIEnv " )
154
156
}
155
157
return tenv
156
158
}
157
159
160
+ fileprivate let initLock = NSLock ( )
161
+
158
162
private func autoInit( ) {
159
- envLock . lock ( )
160
- if envCache . isEmpty && !initJVM( ) {
163
+ initLock . lock ( )
164
+ if jvm == nil && !initJVM( ) {
161
165
report ( " Auto JVM init failed " )
162
166
}
163
- envLock . unlock ( )
167
+ initLock . unlock ( )
164
168
}
165
169
166
170
open func background( closure: @escaping ( ) -> ( ) ) {
@@ -269,15 +273,15 @@ open class JNICore {
269
273
if api. ExceptionCheck ( env ) != 0 , let throwable: jthrowable = api. ExceptionOccurred ( env ) {
270
274
report ( " Exception occured " , file, line )
271
275
thrownLock. lock ( )
272
- thrownCache [ threadKey ] = throwable
276
+ thrownCache [ pthread_self ( ) ] = throwable
273
277
thrownLock. unlock ( )
274
278
api. ExceptionClear ( env )
275
279
}
276
280
return result
277
281
}
278
282
279
283
open func ExceptionCheck( ) -> jthrowable ? {
280
- let currentThread : pthread_t = threadKey
284
+ let currentThread : pthread_t = pthread_self ( )
281
285
if let throwable: jthrowable = thrownCache [ currentThread] {
282
286
thrownLock. lock ( )
283
287
thrownCache. removeValue ( forKey: currentThread)
0 commit comments