ITPub博客

首页 > 应用开发 > IT综合 > 跟着sleep看jvm线程变化

跟着sleep看jvm线程变化

原创 IT综合 作者:千锋Python唐小强 时间:2020-06-28 16:34:30 0 删除 编辑

jvm线程是维护了线程的状态。new,running,waiting,timed waiting,blocked,terminated。我们通过jstack等工具查看的时候,线程状态就是上面的一种。jvm本身是做了一种抽象,我们现在从一个典型的方法,来跟踪查看一下jvm内部又是怎么做状态变化的。

跟着sleep看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自己的状态表示。


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/69923331/viewspace-2700930/,如需转载,请注明出处,否则将追究法律责任。

下一篇: 适配器模式
请登录后发表评论 登录
全部评论

注册时间:2019-05-14

  • 博文量
    995
  • 访问量
    586010