首页 > 应用开发 > IT综合 > 跟着sleep看jvm线程变化
jvm线程是维护了线程的状态。new,running,waiting,timed waiting,blocked,terminated。我们通过jstack等工具查看的时候,线程状态就是上面的一种。jvm本身是做了一种抽象,我们现在从一个典型的方法,来跟踪查看一下jvm内部又是怎么做状态变化的。
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博客 ” ,链接:https://blog.itpub.net/69923331/viewspace-2700930/ ,如需转载,请注明出处,否则将追究法律责任。