[vlc-devel] [PATCH] vout/android: utils: don't cache JNIEnv

Zhao Zhili quinkblack at foxmail.com
Fri Oct 19 14:51:03 CEST 2018


Sometimes android_getEnvCommon() is called in a thread created by the
libvlc user. If the user called DetachCurrentThread first (for example,
use non-optimized RAII strategy to AttachCurrentThread/DetachCurrentThread
each time), then the cached JNIEnv become invalid.

(*jvm)->GetEnv is about 3 times slower than pthread_getspecific in my
test case. Since android_getEnv isn't called in a inner loop, it's not a
bottleneck.
---
 modules/video_output/android/utils.c | 66 ++++++++++++++++--------------------
 1 file changed, 29 insertions(+), 37 deletions(-)

diff --git a/modules/video_output/android/utils.c b/modules/video_output/android/utils.c
index de65746..24df7b6 100644
--- a/modules/video_output/android/utils.c
+++ b/modules/video_output/android/utils.c
@@ -299,27 +299,23 @@ LoadNativeWindowAPI(AWindowHandler *p_awh)
  * Andoid JNIEnv helper
  */
 
-static pthread_key_t jni_env_key;
-static pthread_once_t jni_env_key_once = PTHREAD_ONCE_INIT;
+static pthread_key_t jni_jvm_key;
+static pthread_once_t jni_jvm_key_once = PTHREAD_ONCE_INIT;
 
 /* This function is called when a thread attached to the Java VM is canceled or
  * exited */
 static void
 jni_detach_thread(void *data)
 {
-    JNIEnv *env = data;
-    JavaVM *jvm;
-
-    (*env)->GetJavaVM(env, &jvm);
-    assert(jvm);
+    JavaVM *jvm = data;
     (*jvm)->DetachCurrentThread(jvm);
 }
 
-static void jni_env_key_create()
+static void jni_jvm_key_create()
 {
     /* Create a TSD area and setup a destroy callback when a thread that
-     * previously set the jni_env_key is canceled or exited */
-    pthread_key_create(&jni_env_key, jni_detach_thread);
+     * previously set the jni_jvm_key is canceled or exited */
+    pthread_key_create(&jni_jvm_key, jni_detach_thread);
 }
 
 static JNIEnv *
@@ -327,39 +323,35 @@ android_getEnvCommon(vlc_object_t *p_obj, JavaVM *jvm, const char *psz_name)
 {
     assert((p_obj && !jvm) || (!p_obj && jvm));
 
-    JNIEnv *env;
-
-    pthread_once(&jni_env_key_once, jni_env_key_create);
-    env = pthread_getspecific(jni_env_key);
-    if (env == NULL)
+    if (!jvm)
     {
+        jvm = var_InheritAddress(p_obj, "android-jvm");
         if (!jvm)
-            jvm = var_InheritAddress(p_obj, "android-jvm");
+            return NULL;
+    }
 
-        if (!jvm)
+    JNIEnv *env = NULL;
+    pthread_once(&jni_jvm_key_once, jni_jvm_key_create);
+    /* if GetEnv returns JNI_OK, the thread is already attached to the
+     * JavaVM, so we are already in a java thread, and we don't have to
+     * setup any destroy callbacks */
+    if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2) != JNI_OK)
+    {
+        /* attach the thread to the Java VM */
+        JavaVMAttachArgs args;
+
+        args.version = JNI_VERSION_1_2;
+        args.name = psz_name;
+        args.group = NULL;
+
+        if ((*jvm)->AttachCurrentThread(jvm, &env, &args) != JNI_OK)
             return NULL;
 
-        /* if GetEnv returns JNI_OK, the thread is already attached to the
-         * JavaVM, so we are already in a java thread, and we don't have to
-         * setup any destroy callbacks */
-        if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2) != JNI_OK)
+        /* save jvm which will be used to detach current thread */
+        if (pthread_setspecific(jni_jvm_key, jvm) != 0)
         {
-            /* attach the thread to the Java VM */
-            JavaVMAttachArgs args;
-
-            args.version = JNI_VERSION_1_2;
-            args.name = psz_name;
-            args.group = NULL;
-
-            if ((*jvm)->AttachCurrentThread(jvm, &env, &args) != JNI_OK)
-                return NULL;
-
-            /* Set the attached env to the thread-specific data area (TSD) */
-            if (pthread_setspecific(jni_env_key, env) != 0)
-            {
-                (*jvm)->DetachCurrentThread(jvm);
-                return NULL;
-            }
+            (*jvm)->DetachCurrentThread(jvm);
+            return NULL;
         }
     }
 
-- 
2.9.5





More information about the vlc-devel mailing list