设置和获取当前线程名称(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();
上一篇: PHP使用DOM对XML解析处理操作示例
下一篇: edius色彩平衡特效较色怎么使用?