温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

jvm线程变化是怎样的

发布时间:2021-12-17 13:47:41 阅读:218 作者:iii 栏目:开发技术
开发者测试专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

这篇文章主要介绍“jvm线程变化是怎样的”,在日常操作中,相信很多人在jvm线程变化是怎样的问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”jvm线程变化是怎样的”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

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线程变化是怎样的”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

原文链接:http://blog.itpub.net/69923331/viewspace-2700930/

jvm
AI

开发者交流群×