前言
Java经常会遇到获取当前线程的情况。这时候我们一般通过Thread.currentThread()来获取。接下来,让我们看看这条语句的执行在JVM中做了什么。
简单的例子
下面是一个简单的例子。获取当前线程并打印线程名。输出是”***in & # 8221,也就是主线程。
public class CurrentThreadTest { public static void ***in(String[] args) { Thread t = Thread.currentThread(); System.out.println(t.getName()); }}
当前线程方法
在Thread类中,currentThread是一个静态的局部方法。
public static native Thread currentThread();
Thread.c
Java层声明的本地方法在Thread中实现,c currentThread是在JVM中注册的方法,绑定了JVM_CurrentThread函数,所以实现逻辑在JVM_CurrentThread函数中。逻辑是:
JVMWrapper(“JVM_CurrentThread”)用于调试。通过thread->threadObj()获取 oop,这里的 thread 是在JNI_ENTRY宏中获取到的,详细情况可参考后面的JNI_ENTRY和JNI_END宏。调用JNIHandles::***ke_local函数#define THD "Ljava/lang/Thread;"static JNINativeMethod methods[] = { ... {"currentThread", "()" THD, (void *)&JVM_CurrentThread}, ...};JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass)) JVMWrapper("JVM_CurrentThread"); oop jthread = thread->threadObj(); assert (thread != NULL, "no current thread!"); return JNIHandles::***ke_local(env, jthread);JVM_END
***ke_local函数主要看
thread _ from _ JNI _环境函数,用来获取当前线程。它的逻辑是Java thread * thread _ from _ JNI _ env =(Java thread *)((intptr _ t)env –in _ bytes(JNI _ environment _ offset());也就是直接减去地址偏移量就可以得到JavaThread*。这是因为JavaThread对象包含JNIEnv对象的属性,所以可以通过从偏移量中减去JNIEnv*来计算JavaThread*。最后,检查线程是否已经终止,然后返回线程对象。
得到JavaThread*对象后,给句柄赋值,给句柄赋值oop,变成Java层对象JobProject。
jobject JNIHandles::***ke_local(JNIEnv* env, oop obj) { if (obj == NULL) { return NULL; } else { JavaThread* thread = JavaThread::thread_from_jni_environment(env); assert(Universe::heap()->is_in_reserved(obj), "sanity check"); return thread->active_handles()->allocate_handle(obj); }}static JavaThread* 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(); return NULL; } else { return thread_from_jni_env; } }
“JNI _ entry”和“JNI _ end”宏
这两个宏提取了共同的部分。JNI_END相对简单,只有两个右括号。
#define JNI_ENTRY(result_type, header) JNI_ENTRY_NO_PRESERVE(result_type, header) WeakPreserveExceptionMark __wem(thread);#define JNI_END } }
JNI _入口的主要逻辑:
获取当前执行线程 JavaThread 指针对象。创建 ThreadInVMfromNative 对象。TRACE_CALL ,这里什么都不干。创建 HandleMarkCleaner 对象。将 thread 赋值给 Exceptions 中的 THREAD。校验栈对齐。创建 WeakPreserveExceptionMark 对象。#define JNI_ENTRY_NO_PRESERVE(result_type, header) \extern "C" { \ result_type JNICALL header { \ JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \ ThreadInVMfromNative __tiv(thread); \ debug_only(VMNativeEntryWrapper __vew;) \ VM_ENTRY_BASE(result_type, header, thread)#define VM_ENTRY_BASE(result_type, header, thread) \ TRACE_CALL(result_type, header) \ HandleMarkCleaner __hm(thread); \ Thread* THREAD = thread; \ os::verify_stack_alignment();
本文来自清杉投稿,不代表舒华文档立场,如若转载,请注明出处:https://www.chinashuhua.cn/24/509082.html