跟着sleep看jvm线程变化
< 返回列表时间: 2020-06-29来源:OSCHINA
jvm线程是维护了线程的状态。new,running,waiting,timed waiting,blocked,terminated。我们通过jstack等工具查看的时候,线程状态就是上面的一种。jvm本身是做了一种抽象,我们现在从一个典型的方法,来跟踪查看一下jvm内部又是怎么做状态变化的。
sleep方法入手 public static native void sleep(long millis) throws InterruptedException;
sleep是一个native 方法,我们通过jvm原来来进行跟着(源码来自openjdk11)。 根据jni的规范,我们通过包名或者是jni的注册方式找到了对应的声明。 static JNINativeMethod methods[] = { {"start0", "()V", (void *)&JVM_StartThread}, {"stop0", "(" OBJ ")V", (void *)&JVM_StopThread}, {"isAlive", "()Z", (void *)&JVM_IsThreadAlive}, {"suspend0", "()V", (void *)&JVM_SuspendThread}, {"resume0", "()V", (void *)&JVM_ResumeThread}, {"setPriority0", "(I)V", (void *)&JVM_SetThreadPriority}, {"yield", "()V", (void *)&JVM_Yield}, {"sleep", "(J)V", (void *)&JVM_Sleep}, {"currentThread", "()" THD, (void *)&JVM_CurrentThread}, {"countStackFrames", "()I", (void *)&JVM_CountStackFrames}, {"interrupt0", "()V", (void *)&JVM_Interrupt}, {"isInterrupted", "(Z)Z", (void *)&JVM_IsInterrupted}, {"holdsLock", "(" OBJ ")Z", (void *)&JVM_HoldsLock}, {"getThreads", "()[" THD, (void *)&JVM_GetAllThreads}, {"dumpThreads", "([" THD ")[[" STE, (void *)&JVM_DumpThreads}, {"setNativeName", "(" STR ")V", (void *)&JVM_SetNativeThreadName}, };
接下来我们要跟踪的就是JVM_Sleep了。 我们一点一点来解析这个方法。 首先这里有宏定义。 JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis))
我们展开JVM_ENTRY。 #define JVM_ENTRY(result_type, header) \ extern "C" { \ result_type JNICALL header { \ JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ ThreadInVMfromNative __tiv(thread); \ debug_only(VMNativeEntryWrapper __vew;) \ VM_ENTRY_BASE(result_type, header, thread)
在ThreadInVMfromNative中,发生了一次线程状态的变更。 class ThreadInVMfromNative : public ThreadStateTransition { public: ThreadInVMfromNative(JavaThread* thread) : ThreadStateTransition(thread) { trans_from_native(_thread_in_vm); } ~ThreadInVMfromNative() { trans_and_fence(_thread_in_vm, _thread_in_native); } };
在构造方法中把 JavaThread 的**thread->thread_state()**状态变为了_thread_in_vm。在析构函数中把状态改成了_thread_in_native。这里的__tiv是一个本地对象,只有在栈销毁的时候才会触发析构,也就是说这里的转为_thread_in_native只不过是一瞬间的事情。 展开头结束后,我们再继续往后观察。 JavaThreadSleepState jtss(thread);
在这个构造方法中。把**java_thread->threadObj()**的状态变为了java_lang_Thread::SLEEPING static void set_thread_status(JavaThread* java_thread, java_lang_Thread::ThreadStatus state) { java_lang_Thread::set_thread_status(java_thread->threadObj(), state); }
这里对应的就是java的线程的状态了。 在往下走就直接设置**thread->osthread()**的状态为sleep。 ThreadState old_state = thread->osthread()->get_state(); thread->osthread()->set_state(SLEEPING);
状态到这里全部设置完成。
状态梳理
通过上面的代码,我们可以发现最核心的就是JavaThread的这个对象,他本身代表的jvm中的线程状态。会标识线程是在vm还是线程是在java或者在native。具体的状态如下 enum JavaThreadState { _thread_uninitialized = 0, // should never happen (missing initialization) _thread_new = 2, // just starting up, i.e., in process of being initialized _thread_new_trans = 3, // corresponding transition state (not used, included for completness) _thread_in_native = 4, // running in native code _thread_in_native_trans = 5, // corresponding transition state _thread_in_vm = 6, // running in VM _thread_in_vm_trans = 7, // corresponding transition state _thread_in_Java = 8, // running in Java or in stub code _thread_in_Java_trans = 9, // corresponding transition state (not used, included for completness) _thread_blocked = 10, // blocked in vm _thread_blocked_trans = 11, // corresponding transition state _thread_max_state = 12 // maximum thread state+1 - used for statistics allocation };
这个类同时那种java线程状态的引用。就是java_thread->threadObj()。这个对应的是java的线程状态,这个也是我们jstack看到的状态。 "main" #1 prio=5 os_prio=31 tid=0x00007fee9b809000 nid=0xe03 waiting on condition [0x0000700008d65000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(Native Method) at com.company.Sleep.main(Sleep.java:7)
为什么输出的是timed_waiting(sleep),这个主要是因为格式化输出的原因。 if(status == THREAD_STATUS_NEW){ return "NEW"; }else if(status == THREAD_STATUS_RUNNABLE){ return "RUNNABLE"; }else if(status == THREAD_STATUS_SLEEPING){ return "TIMED_WAITING (sleeping)"; }else if(status == THREAD_STATUS_IN_OBJECT_WAIT){ return "WAITING (on object monitor)"; }else if(status == THREAD_STATUS_IN_OBJECT_WAIT_TIMED){ return "TIMED_WAITING (on object monitor)"; }else if(status == THREAD_STATUS_PARKED){ return "WAITING (parking)"; }else if(status == THREAD_STATUS_PARKED_TIMED){ return "TIMED_WAITING (parking)"; }else if(status == THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER){ return "BLOCKED (on object monitor)"; }else if(status == THREAD_STATUS_TERMINATED){ return "TERMINATED"; } return "UNKNOWN"; }
在状态格式化的时候,把sleeping的归类成为TIMED_WAITING (sleeping)。 于此同时Java Thread还拿着系统的线程thread->osthread()。
小结
jvm中起码有三种状态的变化,一种是代表的java规范中的线程状态(java_thread->threadObj()),一种是表示的jvm代理的系统线程的状态(thread->osthread()),同时还有jvm线程在做转换的一种状态,是vm自己的状态表示。
欢迎关注公众号:肥宅英短
热门排行