JVM如何创建线程

1
2
3
4
5
6
7
Thread t = new Thread(new Runnable() {
@Override
public void run() {

}
});
t.start();

上面这段代码在JVM中是如何实现的呢?

  1. 我们需要熟悉JNI

image

  1. 打开Thread.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public
    class Thread implements Runnable {
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
    registerNatives();
    }
    // ...
    }

了解过JNI,那么我们知道Thread.java一定会对应一个c或c++文件,那么在JVM中Thread.java对应的C文件是openjdk-jdk8u-jdk8u\jdk\src\share\native\java\lang\Thread.c

打开Thread.c,发现这个文件很简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include "jni.h"
#include "jvm.h"

#include "java_lang_Thread.h"

#define THD "Ljava/lang/Thread;"
#define OBJ "Ljava/lang/Object;"
#define STE "Ljava/lang/StackTraceElement;"
#define STR "Ljava/lang/String;"

#define ARRAY_LENGTH(a) (sizeof(a)/sizeof(a[0]))

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},
};

#undef THD
#undef OBJ
#undef STE
#undef STR

JNIEXPORT void JNICALL
Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls)
{
(*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));
}

我们可以看到methods定义了所有的native方法。Java_java_lang_Thread_registerNatives恰好对应的是java.lang.Thread中的registerNatives()方法。

当执行t.start()的时候,发生了什么呢?

我们知道在执行t.start()的时候,jdk代码中会去执行start0的native方法那么对应的就是JVM_StartThread。

我们找到JVM_StartThread

openjdk-jdk8u-jdk8u\hotspot\src\share\vm\prims\jvm.h

openjdk-jdk8u-jdk8u\hotspot\src\share\vm\prims\jvm.cpp

在C/C++中.h .hpp文件为头文件,可以理解为啥呢,Java中的接口文件(类似哈,请不要较真)

.c .cpp为具体的实现文件。

在jvm.cpp找到JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))创建线程的入口。

image

其中第6步的new JavaThread在openjdk-jdk8u-jdk8u\hotspot\src\share\vm\runtime\thread.cpp

JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz)

在调用pthread_create的时候,这里涉及到具体的操作系统

1
2
3
4
5
6
7
8
9
10
linux:
openjdk-jdk8u-jdk8u\hotspot\src\os\linux\vm\os_linux.cpp
windows:
openjdk-jdk8u-jdk8u\hotspot\src\os\windows\vm\os_windows.cpp
bsd:
openjdk-jdk8u-jdk8u\hotspot\src\os\bsd\vm\os_bsd.cpp
aix:
openjdk-jdk8u-jdk8u\hotspot\src\os\aix\vm\os_aix.cpp
solaris:
openjdk-jdk8u-jdk8u\hotspot\src\os\solaris\vm\os_solaris.cpp