目录
1)上节课说过了 为什么入口是这里,演示的时候到97 行,但是下面没东西 我直接从125 行开始) main.c 125 行
7)后面就是当前线程阻塞了,看javamain 方法,进入到 java.c 371
8)进入到 jni.cpp 5115 (也即是 JNI_CreateJavaVM 方法),我们跳到5166行
14)回调main函数结束,当前线程 还记得之前的 第6步进入到 java_md_solinux.c pthread_join(tid, &tmp) 吗? 此时就都结束了。
-
为什么要研究main
作为java的程序入口,作为java程序员不能对源码的流程一点都不了解吧。另外main的流程也是比较经典的源码debug分析,流程还是比较容易理解并学习的。
2.大体猜想,并带着疑问源码debug
-
其他的方法都是可以明显看出代码调用的,main没有。。。那肯定是jvm帮我们创建的
-
main也是作为一个线程,那线程实际是在哪里呢?java层面吗? 肯定不可能。为什么呢? 线程是有cpu 调度的最小执行单元,请问jvm有cpu吗?所以总结一句话 java中没有线程,线程操作是jvm层操作的,而且可以看做操作系统在jvm层的一个代理。(个人理解 有点拗口,理解下)
-
具体debug过程
-
1)上节课说过了 为什么入口是这里,演示的时候到97 行,但是下面没东西 我直接从125 行开始) main.c 125 行
2)进入 到 java.c 248
##主要是验证 jni接口是否正常 ,后续使用
LoadJavaVM(jvmpath, &ifn)
3)进入到 java.c 299 方法
4)进入到 java_md_solinux.c 1062
JVMInit(InvocationFunctions* ifn, jlong threadStackSize,
int argc, char **argv,
int mode, char *what, int ret)
{
ShowSplashScreen();
return ContinueInNewThread(ifn, threadStackSize, argc, argv, mode, what, ret);//此时开启新线程了
}
5)进入到 java.c 1904
rslt = ContinueInNewThread0(JavaMain, threadStackSize, (void*)&args);//创建一个新线程来创建虚拟机并触发JavaMain方法
6)进入到 java_md_solinux.c 1013
##创建内核线程 并阻塞当前的线程等到 main线程完成
if (pthread_create(&tid, &attr, (void *(*)(void*))continuation, (void*)args) == 0) {
void * tmp;
pthread_join(tid, &tmp);
rslt = (int)tmp;
}
7)后面就是当前线程阻塞了,看javamain 方法,进入到 java.c 371
##初始化java 虚拟机
InitializeJVM(&vm, &env, &ifn) //371 行
转到:java.c 1145行
r = ifn->CreateJavaVM(pvm, (void **)penv, &args);
8)进入到 jni.cpp 5115 (也即是 JNI_CreateJavaVM 方法),我们跳到5166行
result = Threads::create_vm((JavaVMInitArgs*) args, &can_try_again); //这里创建虚拟机入口
9)我们跳到 thread.cpp 3393 行
JavaThread* main_thread = new JavaThread(); //3393行 此时并未创建线程 ,只是创建个对象
main_thread->set_as_starting_thread() // 3405行
10) 看下 3405行 怎么关联的,我们跳到 thread.cpp 978 再跳到 os_linux.cpp os::create_attached_thread(JavaThread* thread) 方法 1010行
##可以看出 jvm线程跟内核线程是 一一对应的!!
osthread->set_thread_id(os::Linux::gettid()); //将当前内核线程id等信息设置进osthread对象中
osthread->set_pthread_id(::pthread_self()); //为关联java线程和内核线程做准备
thread->set_osthread(osthread); //在此产生关联,将内核线程 jvm线程 java线程进行关联
11)thread.cpp 3505 行
oop thread_object = create_initial_thread(thread_group, main_thread, CHECK_0); //映射到java中的main线程
进入到 thread.cpp 1022 行 看看main线程的真正创建场地,可以看到 javaCalls。。。大家都懂 后面会进行回调,触发运行main函数
12)java.c 439行 加载main函数所在的类文件
mainClass = LoadMainClass(env, mode, what);
13)java.c 472行 回调main函数
(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs); //执行main方法
14)回调main函数结束,当前线程 还记得之前的 第6步进入到 java_md_solinux.c pthread_join(tid, &tmp) 吗? 此时就都结束了。
4 流程总结 与画图
主要是 创建了个线程,此线程中创建了内核线程,并等待javamain函数的完成,javamain函数 主要是把内核线程跟jvm线程一些信息做了绑定,并开启线程 最后回调main函数,完成了整个流程。(文笔不好,特别希望有人 帮我总结下 。。。我更新下)
备注:如有总结不妥之处,请留言。