前言
java 中经常会遇到要获取当前线程的情况。这时一般我们就会通过Thread.currentThread()来获取。接下去就看看执行该语句在 JVM 中做了什么吧。
简单例子
以下是一个简单的例子。获取当前线程并打印线程名称。输出是”main”。即主线程。
publicclassCurrentThreadTest{ publicstaticvoidmain(String[]args){ Threadt=Thread.currentThread(); System.out.println(t.getName()); } }
currentThread方法
在 Thread 类中。currentThread是一个静态且本地方法。
publicstaticnativeThreadcurrentThread();
Thread.c
Java 层声明的本地方法对应实现在 Thread.c 中。currentThread是一个注册到 JVM 中的方法。它与 JVM 中的JVM_CurrentThread函数绑定了。所以实现逻辑在JVM_CurrentThread函数里。逻辑为:
-
JVMWrapper(“JVM_CurrentThread”)用于调试。
-
通过thread->threadObj()获取 oop。这里的 thread 是在JNI_ENTRY宏中获取到的。详细情况可参考后面的JNI_ENTRY和JNI_END宏。
-
调用JNIHandles::make_local函数
#defineTHD"Ljava/lang/Thread;" staticJNINativeMethodmethods[]={ ... {"currentThread","()"THD,(void*)&JVM_CurrentThread}, ... }; JVM_ENTRY(jobject,JVM_CurrentThread(JNIEnv*env,jclassthreadClass)) JVMWrapper("JVM_CurrentThread"); oopjthread=thread->threadObj(); assert(thread!=NULL,"nocurrentthread!"); returnJNIHandles::make_local(env,jthread); JVM_END
make_local函数中主要看
thread_from_jni_environment函数。它用于获取当前线程。它的逻辑为JavaThread *thread_from_jni_env = (JavaThread*)((intptr_t)env – in_bytes(jni_environment_offset()));。即直接通过地址偏移来做减法计算得到JavaThread*。这是因为 JavaThread 对象包含了 JNIEnv 对象属性。所以可以通过JNIEnv*与偏移做减法来算出JavaThread*。最后还要检查线程是否已经终止状态。没有终止才返回该线程对象。
获取到JavaThread*对象后。分配句柄并将 oop 赋给句柄。并且转成 Java 层的对象 jobject。
jobjectJNIHandles::make_local(JNIEnv*env,oopobj){ if(obj==NULL){ returnNULL; }else{ JavaThread*thread=JavaThread::thread_from_jni_environment(env); assert(Universe::heap()->is_in_reserved(obj),"sanitycheck"); returnthread->active_handles()->allocate_handle(obj); } } staticJavaThread*thread_from_jni_environment(JNIEnv*env){ JavaThread*thread_from_jni_env=(JavaThread*)((intptr_t)env-in_bytes(jni_environment_offset())); if(thread_from_jni_env->is_terminated()){ thread_from_jni_env->block_if_vm_exited(); returnNULL; }else{ returnthread_from_jni_env; } }
`JNI_ENTRY`和`JNI_END`宏
这两个宏将共同的部分都抽离出来了。其中JNI_END比较简单。就两个结束大括号。
#defineJNI_ENTRY(result_type,header)JNI_ENTRY_NO_PRESERVE(result_type,header)WeakPreserveExceptionMark__wem(thread); #defineJNI_END}}
JNI_ENTRY主要逻辑:
-
获取当前执行线程 JavaThread 指针对象。
-
创建 ThreadInVMfromNative 对象。
-
TRACE_CALL 。这里什么都不干。
-
创建 HandleMarkCleaner 对象。
-
将 thread 赋值给 Exceptions 中的 THREAD。
-
校验栈对齐。
-
创建 WeakPreserveExceptionMark 对象。
#defineJNI_ENTRY_NO_PRESERVE(result_type,header)\ extern"C"{\ result_typeJNICALLheader{\ JavaThread*thread=JavaThread::thread_from_jni_environment(env);\ assert(!VerifyJNIEnvThread||(thread==Thread::current()),"JNIEnvisonlyvalidinsamethread");\ ThreadInVMfromNative__tiv(thread);\ debug_only(VMNativeEntryWrapper__vew;)\ VM_ENTRY_BASE(result_type,header,thread) #defineVM_ENTRY_BASE(result_type,header,thread)\ TRACE_CALL(result_type,header)\ HandleMarkCleaner__hm(thread);\ Thread*THREAD=thread;\ os::verify_stack_alignment();
以上就是由优质生活领域创作者 生活常识网 整理编辑的,如果觉得有帮助欢迎收藏转发~
本文地址:http://www.shenzhoubaby.com/5003.html,转载请说明来源于:生活常识网
声明:本站部分文章来自网络,如无特殊说明或标注,均为本站原创发布。如若本站内容侵犯了原著者的合法权益,可联系@qq.com进行处理。分享目的仅供大家学习与参考,不代表本站立场。