欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-11-27 14:44:10
前言java 中经常会遇到要获取当前线程的情况,这时一般我们就会通过thread.currentthread()来获取,接下去就看看执行该语句在 jvm 中做了什么吧。简单例子以下是一个简单的例子,获...

前言

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();