@@ -51,6 +51,10 @@ SWIGINTERN int Swig::GetThreadName(char *name, size_t len) {
51
51
52
52
#endif
53
53
54
+ #if defined(SWIG_JAVA_DETACH_ON_THREAD_END)
55
+ #include <pthread.h>
56
+ #endif
57
+
54
58
namespace Swig {
55
59
56
60
/* Java object wrapper */
@@ -133,13 +137,30 @@ namespace Swig {
133
137
}
134
138
}
135
139
140
+ #if defined(SWIG_JAVA_DETACH_ON_THREAD_END)
141
+ static void detach(void *jvm) {
142
+ static_cast<JavaVM *>(jvm)->DetachCurrentThread();
143
+ }
144
+
145
+ static void make_detach_key() {
146
+ pthread_key_create(&detach_key_, detach);
147
+ }
148
+
149
+ /* thread-local key to register a destructor */
150
+ static pthread_key_t detach_key_;
151
+ #endif
152
+
136
153
private:
137
154
/* pointer to Java object */
138
155
jobject jthis_;
139
156
/* Local or global reference flag */
140
157
bool weak_global_;
141
158
};
142
159
160
+ #if defined(SWIG_JAVA_DETACH_ON_THREAD_END)
161
+ pthread_key_t JObjectWrapper::detach_key_;
162
+ #endif
163
+
143
164
/* Local JNI reference deleter */
144
165
class LocalRefGuard {
145
166
JNIEnv *jenv_;
@@ -201,9 +222,19 @@ namespace Swig {
201
222
#else
202
223
director_->swig_jvm_->AttachCurrentThread(jenv, &args);
203
224
#endif
225
+
226
+ #if defined(SWIG_JAVA_DETACH_ON_THREAD_END)
227
+ // At least on Android 6, detaching after every call causes a memory leak.
228
+ // Instead, register a thread desructor and detach only when the thread ends.
229
+ // See https://developer.android.com/training/articles/perf-jni#threads
230
+ static pthread_once_t once = PTHREAD_ONCE_INIT;
231
+
232
+ pthread_once(&once, JObjectWrapper::make_detach_key);
233
+ pthread_setspecific(JObjectWrapper::detach_key_, director->swig_jvm_);
234
+ #endif
204
235
}
205
236
~JNIEnvWrapper() {
206
- #if !defined(SWIG_JAVA_NO_DETACH_CURRENT_THREAD)
237
+ #if !defined(SWIG_JAVA_DETACH_ON_THREAD_END) && !defined( SWIG_JAVA_NO_DETACH_CURRENT_THREAD)
207
238
// Some JVMs, eg jdk-1.4.2 and lower on Solaris have a bug and crash with the DetachCurrentThread call.
208
239
// However, without this call, the JVM hangs on exit when the thread was not created by the JVM and creates a memory leak.
209
240
if (env_status == JNI_EDETACHED)
0 commit comments