Added functions to attach/detach native threads to the JVM
authorTobias Brunner <tobias@strongswan.org>
Sat, 14 Jul 2012 14:06:12 +0000 (16:06 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 8 Aug 2012 13:41:04 +0000 (15:41 +0200)
Even though native threads are automatically detached from the JVM with
help of a thread-local destructor it is recommended to detach as soon as
possible as local JNI references are not freed until a thread detaches.

src/frontends/android/jni/libandroidbridge/android_jni.c
src/frontends/android/jni/libandroidbridge/android_jni.h

index 3295745..0acebbb 100644 (file)
@@ -18,6 +18,7 @@
 #include "android_jni.h"
 
 #include <library.h>
+#include <threading/thread_value.h>
 
 /**
  * JVM
@@ -27,6 +28,40 @@ static JavaVM *android_jvm;
 jclass *android_charonvpnservice_class;
 
 /**
+ * Thread-local variable. Only used because of the destructor
+ */
+static thread_value_t *androidjni_threadlocal;
+
+/**
+ * Thread-local destructor to ensure that a native thread is detached
+ * from the JVM even if androidjni_detach_thread() is not called.
+ */
+static void attached_thread_cleanup(void *arg)
+{
+       (*android_jvm)->DetachCurrentThread(android_jvm);
+}
+
+/*
+ * Described in header
+ */
+void androidjni_attach_thread(JNIEnv **env)
+{
+       (*android_jvm)->AttachCurrentThread(android_jvm, env, NULL);
+       /* use a thread-local value with a destructor that automatically detaches
+        * the thread from the JVM before it terminates, if not done manually */
+       androidjni_threadlocal->set(androidjni_threadlocal, (void*)*env);
+}
+
+/*
+ * Described in header
+ */
+void androidjni_detach_thread()
+{
+       androidjni_threadlocal->set(androidjni_threadlocal, NULL);
+       (*android_jvm)->DetachCurrentThread(android_jvm);
+}
+
+/**
  * Called when this library is loaded by the JVM
  */
 jint JNI_OnLoad(JavaVM *vm, void *reserved)
@@ -40,6 +75,8 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved)
                return -1;
        }
 
+       androidjni_threadlocal = thread_value_create(attached_thread_cleanup);
+
        android_charonvpnservice_class =
                                (*env)->NewGlobalRef(env, (*env)->FindClass(env,
                                                JNI_PACKAGE_STRING "/CharonVpnService"));
@@ -47,3 +84,11 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved)
        return JNI_VERSION_1_6;
 }
 
+/**
+ * Called when this library is unloaded by the JVM
+ */
+void JNI_OnUnload(JavaVM *vm, void *reserved)
+{
+       androidjni_threadlocal->destroy(androidjni_threadlocal);
+}
+
index 8f8d302..2a8d3a7 100644 (file)
  */
 extern jclass *android_charonvpnservice_class;
 
+/**
+ * Attach the current thread to the JVM
+ *
+ * As local JNI references are not freed until the thread detaches
+ * androidjni_detach_thread() should be called as soon as possible.
+ * If it is not called a thread-local destructor ensures that the
+ * thread is at least detached as soon as it terminates.
+ *
+ * @param env          JNIEnv
+ */
+void androidjni_attach_thread(JNIEnv **env);
+
+/**
+ * Detach the current thread from the JVM
+ *
+ * Call this as soon as possible to ensure that local JNI references are freed.
+ */
+void androidjni_detach_thread();
+
 #endif /** ANDROID_JNI_H_ @}*/