以下是Thread的start方法源码:
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
注意力集中到start0(),一个本地方法:private native void start0();
Thread类要调用本地方法,首先要向jvm注册,所以Thread类的开头便是:
public class Thread implements Runnable {
/* Make sure registerNatives is the first thing <clinit> does. */
private static native void registerNatives();
static {
registerNatives();
}
...
..
}
本地方法 registerNatives 定义在Thread.c文件中,定义了各个操作系统都要用到的关于线程的公用数据和操作,代码如下:
JNIEXPORT void JNICALL Java_Java_lang_Thread_registerNatives (JNIEnv *env, jclass cls){
(*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));
}
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},
};
可以看出Java线程调用start的方法,实际上会调用到JVM_StartThread方法。
在 jvm.cpp 中,有如下代码段:JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
…
native_thread = new JavaThread(&thread_entry, sz);
…
这里JVM_ENTRY是一个宏,用来定义JVM_StartThread函数,可以看到函数内创建了真正的平台相关的本地线程,
其线程函数是thread_entry,代码如下:
static void thread_entry(JavaThread* thread, TRAPS) {
HandleMark hm(THREAD);
Handle obj(THREAD, thread->threadObj());
JavaValue result(T_VOID);
JavaCalls::call_virtual(&result,obj,
KlassHandle(THREAD,SystemDictionary::Thread_klass()),
vmSymbolHandles::run_method_name(),
vmSymbolHandles::void_method_signature(),THREAD);
}
可以看到调用了vmSymbolHandles::run_method_name方法,这是在vmSymbols.hpp用宏定义的:
class vmSymbolHandles: AllStatic {
…
template(run_method_name,"run")
…
}
至于run_method_name是如何声明定义的,就不再一一赘述了,感兴趣的读者可以自行查看 JVM 的源代码。
Java 线程调用关系图:
综上所述,Java线程的创建调用过程如上图所示
Java线程的start方法会创建一个本地线程(通过调用JVM_StartThread),
该线程的线程函数是定义在jvm.cpp中的thread_entry,由其再进一步回调run方法。
参考:https://www.ibm.com/developerworks/cn/java/j-lo-processthread/#icomments