JVM初始化Main线程创建的流程(从OpenJDK8源码到Linux源码的线程创建)

JVM本质是动态链接库(Windows下为.dll文件,Linux下为.so文件),作为Java的虚拟机运行在操作系统的进程空间中,为Java语言提供类加载机制,热点编译,GC回收机制等,同时也为JDK函数的封装提供了JNI支持,即调用C/C++函数接口。此文将从JVM的启动流程开始向底层分析Main线程的创建(Linux平台下)。
在这里插入图片描述

OpenJDK8:

所有主函数的入口点都是Main函数,由操作系统fork一个子进程去调度执行Main函数.Window下为WinMain函数,Linux下为main函数,所以JVM作为C++编写的程序,也需要提供了一个启动函数,由操作系统调度执行,这个启动函数就是main.c文件下的main函数。
在这里插入图片描述
这里请看JLI_Launch函数,继续深入:
在这里插入图片描述
此时JVM.dll还未被启动,所以需要加载这个动态链接库,类比文件操作,第一步肯定是获得该文件的路径,第二步open打开该文件,加载到进程空间中,第三步执行该动态链接库的main函数进行启动。
JIL_Launch函数的作用便是如此。请看源码:
第一步:获取jvm.dll的文件路径
在这里插入图片描述
第二步:dlopen,将文件从磁盘加载到内存。其中符号表的作用为内存映射,是方法名,变量名等信息的内存地址映射表。
在这里插入图片描述
第三步:jvm.dll已经加载到内存,剩下的就是创建线程执行主函数即可。
下述即开始创建线程,在堆内存中开辟一个线程栈,栈大小由threadStackSize传入
在这里插入图片描述
最后看ConinueInNewThrerad0方法:在这里插入图片描述可以看见在JDK8的源码中使用了pthread_create函数,这个函数是由C语言的函数库glibc提供的,用于创建线程,接下来我们继续到glibc的源码中查看pthread_create的调用过程。

glibc-2.19:

废话不多说,上源码:
在这里插入图片描述
在这里插入图片描述
这里线程的创建,必然需要先分配线程栈,这里传入了线程元数据的结构体,在堆中fork(可以理解为创建,copy了父进程的信息)了线程栈,用于保存线程执行过程中生成的临时数据,当线程执行结束,一出栈,栈中数据自然也被回收了。这里是通过mmap映射的内存,而不是brk指针分配的,因为这段内存的内存大小不能特别小,否则线程中数据处理的能力将会十分有限!所以使用mmap映射物理内存,复制了页表。实现了函数行为即代码段共享,数据独立的特性,不会占据多余的物理内存。
内存都分配好了,剩下的就是创建了!
在这里插入图片描述
这里do_clone方法便开始了线程的fork!请继续看:
在这里插入图片描述

来到了Linux的系统调用,让Linux对当前进程进行clone及克隆创建一个新的线程,这个线程与当前进程共享内存,这里补充一下线程出现缘由:在Linux源码中线程和进程共用task_struct结构体,所以说两者本质都是一样的,而线程为什么出现呢?因为最初是为了减轻程序多进程带来的负担以及进程切换损耗的效率
每开辟一个进程都需要加载程序的代码段,数据段,堆栈段到内存,当一个大型的程序,它的代码本身就非常庞大,若打开多个程序进程的情况下,代码重复被加载到内存中,这就造成了代码冗余!重复的代码多次的出现在内存中,消耗极大的资源。同时进程切换在系统调度方面需要切换SS堆栈段寄存器和SP栈指针寄存器等。为了避免造成更大的性能损耗,随即就出出现了一个轻量级的进程——即为线程。
在这里插入图片描述
线程的出现使得实际物理内存的代码段数据段等信息共享!实现了数据独立,行为(函数)共享,而sys_clone方法干的正是此事。

Linux 2.6.0:

这里展示的是CPU i386的sys_clone方法:
在这里插入图片描述
可以看到,这里就是调用了do_fork方法,与父进程创建子进程的方式无异,只不过参数的复制不同而已
在这里插入图片描述
copy_process,进程创建时需要对代码段,数据段,堆栈段等信息进行copy,即重新开辟一段物理内存保存,而线程创建则不然,只需copy页表,物理内存中的数据段(只读数据段不共享),代码段等信息共享即可。创建成功后返回一个新的task_struct,这个方法的执行结束也就标识了一个新的线程/进程结构体task_struct创建的完成,也代表了Main线程的创建完成,至此结束。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值