Added functions to attach/detach native threads to the JVM
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.
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
#include "android_jni.h"
|
#include "android_jni.h"
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
|
#include <threading/thread_value.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JVM
|
* JVM
|
||||||
@@ -26,6 +27,40 @@ static JavaVM *android_jvm;
|
|||||||
|
|
||||||
jclass *android_charonvpnservice_class;
|
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
|
* Called when this library is loaded by the JVM
|
||||||
*/
|
*/
|
||||||
@@ -40,6 +75,8 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
androidjni_threadlocal = thread_value_create(attached_thread_cleanup);
|
||||||
|
|
||||||
android_charonvpnservice_class =
|
android_charonvpnservice_class =
|
||||||
(*env)->NewGlobalRef(env, (*env)->FindClass(env,
|
(*env)->NewGlobalRef(env, (*env)->FindClass(env,
|
||||||
JNI_PACKAGE_STRING "/CharonVpnService"));
|
JNI_PACKAGE_STRING "/CharonVpnService"));
|
||||||
@@ -47,3 +84,11 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved)
|
|||||||
return JNI_VERSION_1_6;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,4 +43,23 @@
|
|||||||
*/
|
*/
|
||||||
extern jclass *android_charonvpnservice_class;
|
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_ @}*/
|
#endif /** ANDROID_JNI_H_ @}*/
|
||||||
|
|||||||
Reference in New Issue
Block a user