native start0追踪到hotspot源码中
private void native start0();
native的原理是调用 JNI,而 Hotspot 源码的惯例则是,通常一个 Xxx.java 对应一个 Xxx.c,
以下举三个例子:
Java 类 | 相对于OpenJDK源码的路径 |
---|---|
java.lang.Thread | jdk/src/share/native/java/lang/Thread.c |
java.lang.String | jdk/src/share/native/java/lang/String.c |
java.lang.System | jdk/src/share/native/java/lang/System.c |
所以 native start0 对应调用是以下 JNINativeMethod 数组中第一个元素的 JVM_StartThread 函数。
static JNINativeMethod methods[] = {
{"start0", "()V", (void *)&JVM_StartThread},...}
以 JVM_
开头的函数,可以到 jvm.cpp
中寻找实现。(即 hotspot/src/share/vm/prims/jvm.cpp)
JVM_StartThread 中重要的代码
1. 创建C++层面的JavaThread
JavaThread-OSThread-pthread
JavaThread 和 OSThread 之间的关系?
JavaThread 的父类成员变量 _osthread
保存着对应的 OSThread 对象。
OSThread 和 pthread(Linux 操作系统线程)之间的关系?
OSThread 的成员变量 _pthread_id
保存着 pthread_create 的返回值,所有 Linux pthread 相关 API 都需要用到 pthread_t 对象。
因此,native_thread = new JavaThread(&thread_entry, sz);
创建C++层面的JavaThread,构建起 JavaThread对象 与 OSThread对象,OSThread对象与 OS线程对象(例如 Linux中的 pthread)之间的关联。
2. JavaThread的prepare方法
void JavaThread::prepare(jobject jni_thread, ThreadPriority prio)
- 为Java的Thread对象对应C++的oop对象设置C++的JavaThread对象。即构建 Java 的Thread对象与JavaThread对象的关联;
- 把创建的所有线程放入到一个容器中去。容器的作用是在 GC 的 STW 过程中,遍历到当前进程的所有线程;
3. Thread::start(native_thread)
os线程函数java_start中怎么执行的Java的线程的run方法?
static void *java_start(Thread *thread) {}
静态方法 java_start 的函数体内最后一行调用 thread->run();
void JavaThread::run() {}
JavaThread类成员函数run的函数体内最后一行调用 thread_main_inner()
void JavaThread::thread_main_inner() {}
JavaThread类成员函数thread_main_inner内有一行调用 this->entry_point()(this, this);
entry_point其实执行是的静态函数 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()),
vmSymbols::run_method_name(),
vmSymbols::void_method_signature(),
THREAD);
}
JVM是如何执行Java的run方法的?
继续跟踪 call_virtual 函数到该位置:
void JavaCalls::call(JavaValue* result, methodHandle method, JavaCallArguments* args, TRAPS) {
// JavaCalls::call_helper 也是一个成员函数
os::os_exception_wrapper(call_helper, result, &method, args, THREAD);
}
函数 os::os_exception_wrapper 实际会调用 call_helper 函数,而 call_helper 函数中有一处调用 call_stub 的代码:
StubRoutines::call_stub()(
(address)&link,
// (intptr_t*)&(result->_value), // see NOTE above (compiler problem)
result_val_address, // see NOTE above (compiler problem)
result_type,
method(),
entry_point,
args->parameters(),
args->size_of_parameters(),
CHECK
);
这段 call_stub 的调用,是 JVM 和 Java 的分水岭,越过他就进入到 Java 的世界中。
JVM_StartThread运行在哪个线程中?
JVM_StartThread 运行在 main 线程中。
main 线程的创建代码在
// 当前函数运行在“主控线程”中
int ContinueInNewThread0(int (JNICALL *continuation)(void *), jlong stack_size, void * args) {
// 创建pthread前的准备工作
int rslt;
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
// main线程的线程属性————JOINABLE
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
// 在主控线程中创建一个main线程
if (pthread_create(&tid, &attr, (void *(*)(void*))continuation, (void*)args) == 0) {
void * tmp;
// 主控线程等待 main线程执行完
pthread_join(tid, &tmp);
rslt = (int)tmp;
}
// 清理工作
}