第25页 2.4.3 JNIEnv介绍
RednaxelaFX (Script Ahead, Code Behind)
在读 深入理解Android
- 章节名:2.4.3 JNIEnv介绍
- 页码:第25页
可能会有人担心每次要获取JNIEnv*都去调用JNI提供的AttachCurrentThread()会不会很慢。 可以对比一下标准Java SE的JVM的实现。以Oracle JDK/OpenJDK里的HotSpot VM为例,它内部以thread local的方式保存着每个线程对应在JVM里的数据结构(Thread/JavaThread),这个Thread结构持有该线程对应的JNIEnv*。某个线程如果已经在JVM里注册为Java线程,那么要执行的代码其实很简单,开销不大:
static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool daemon) { JavaVMAttachArgs *args = (JavaVMAttachArgs *) _args; Thread* t = ThreadLocalStorage::get_thread_slow(); if (t != NULL) { // If the thread has been attached this operation is a no-op *(JNIEnv**)penv = ((JavaThread*) t)->jni_environment(); return JNI_OK; } // ... }这个ThreadLocalStorage底下使用的是操作系统提供的thread local存储(TLS)功能。在Windows上用Tls*系的Win32 API,在Linux上用pthread的pthread_getspecific/pthread_setspecific等函数。 Dalvik VM是怎么实现的呢? vm/Jni.cpp
static jint attachThread(JavaVM* vm, JNIEnv** p_env, void* thr_args, bool isDaemon) { JavaVMAttachArgs* args = (JavaVMAttachArgs*) thr_args; /* * Return immediately if we're already one with the VM. */ Thread* self = dvmThreadSelf(); if (self != NULL) { *p_env = self->jniEnv; return JNI_OK; } // ... }这里的dvmThreadSelf()底下也是依赖pthread的thread local存储。跟HotSpot VM几乎是一样的逻辑。 如果我们不想每次获取线程对应的JNIEnv*都调用AttachCurrentThread(),那要么得自己发明一种thread local的数据结构或者是用个map记住线程与JNIEnv*的映射关系,要么也去依赖操作系统的thread local存储功能。此处既然JVM已经帮我们实现了thread local的包装,还是每次都调用AttachCurrentThread()简单方便,而且也不慢。
RednaxelaFX对本书的所有笔记 · · · · · ·
-
第24页 2.4.3 JNIEnv介绍
图2-3 JNIEnv内部结构简图 书中的图2-3在JNI规范有相似的图,在第2章Design Overview的Figure...
-
第19页 2.4.1 注册JNI函数
需要解释一下静态方法中native函数是如何找到对应的JNI函数的。其实,过程非常简单: 当Java...
-
第25页 2.4.3 JNIEnv介绍
-
第88页 4.5.1 虚拟机heapsize的限制
在分析zygote创建虚拟机的时候,我们说过系统默认设置的Java虚拟机堆栈最大为16MB “堆栈”在...
-
第18页 2.4.1 注册JNI函数
正如代码中注释的那样,native_init函数对应的JNI函数是android_media_MediaScanner_native_i...
说明 · · · · · ·
表示其中内容是对原文的摘抄