设置和获取当前线程名称(java代码大全及详解)

前言

Java 中经常会遇到要获取当前线程的情况,这时一般我们就会通过Thread.currentThread()来获取,接下去就看看执行该语句在 JVM 中做了什么吧。

简单例子

以下是一个简单的例子,获取当前线程并打印线程名称,输出是”main”,即主线程。

public class CurrentThreadTest { public static void main(String[] args) { Thread t = Thread.currentThread(); System.out.println(t.getName()); }}

currentThread方法

在 Thread 类中,currentThread是一个静态且本地方法。

public static native Thread currentThread();

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函数
#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::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。

jobject JNIHandles::make_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_ENTRY主要逻辑:

  • 获取当前执行线程 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(); 
(0)
小多多的头像小多多创始人

相关推荐

发表回复

登录后才能评论