java main 源码分析流程,老鸟你会了吗?全网最详细

目录

为什么要研究main

    2.大体猜想,并带着疑问源码debug

具体debug过程

1)上节课说过了 为什么入口是这里,演示的时候到97 行,但是下面没东西 我直接从125 行开始) main.c 125 行

2)进入 到 java.c 248

3)进入到 java.c 299 方法

4)进入到 java_md_solinux.c 1062

5)进入到 java.c 1904

6)进入到 java_md_solinux.c 1013

7)后面就是当前线程阻塞了,看javamain 方法,进入到 java.c 371

8)进入到 jni.cpp 5115 (也即是 JNI_CreateJavaVM 方法),我们跳到5166行

9)我们跳到 thread.cpp 3393 行

10) 看下 3405行 怎么关联的,我们跳到 thread.cpp 978 再跳到 os_linux.cpp os::create_attached_thread(JavaThread* thread) 方法 1010行

11)thread.cpp 3505 行

12)java.c 439行 加载main函数所在的类文件

13)java.c 472行 回调main函数

14)回调main函数结束,当前线程 还记得之前的 第6步进入到 java_md_solinux.c pthread_join(tid, &tmp) 吗? 此时就都结束了。

4 流程总结 与画图


  1. 为什么要研究main

作为java的程序入口,作为java程序员不能对源码的流程一点都不了解吧。另外main的流程也是比较经典的源码debug分析,流程还是比较容易理解并学习的。

    2.大体猜想,并带着疑问源码debug

  1. 其他的方法都是可以明显看出代码调用的,main没有。。。那肯定是jvm帮我们创建的

  2. main也是作为一个线程,那线程实际是在哪里呢?java层面吗? 肯定不可能。为什么呢? 线程是有cpu 调度的最小执行单元,请问jvm有cpu吗?所以总结一句话 java中没有线程,线程操作是jvm层操作的,而且可以看做操作系统在jvm层的一个代理。(个人理解 有点拗口,理解下)

  3. 具体debug过程

  4. 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函数,完成了整个流程。(文笔不好,特别希望有人 帮我总结下 。。。我更新下)

备注:如有总结不妥之处,请留言。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫猫大神

有帮助的话,请打赏官人一下哦!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值