<menu id="ycqsw"></menu><nav id="ycqsw"><code id="ycqsw"></code></nav>
<dd id="ycqsw"><menu id="ycqsw"></menu></dd>
  • <nav id="ycqsw"></nav>
    <menu id="ycqsw"><strong id="ycqsw"></strong></menu>
    <xmp id="ycqsw"><nav id="ycqsw"></nav>
  • 設置和獲取當前線程名稱(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(); 
    

    版權聲明:本文內容由互聯網用戶自發貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如發現本站有涉嫌抄襲侵權/違法違規的內容, 請發送郵件至 舉報,一經查實,本站將立刻刪除。

    發表評論

    登錄后才能評論
    国产精品区一区二区免费