JVM的启动过程

为了分析Java的启动过程,需要查看JDK的源代码。可以从这里拿源代码:

GitHub - zxiaofan/JDK: Source code for multiple JDK versions(1.6/1.7/1.8/1.9/10 JDK’s src.zip), Only for learning; “rt_debug.jar” can be used for debugging.

从github里面clone好以后,查看java的源代码:

java这个程序,是C代码,查看java.c的源代码。重点看JavaMain(...)函数:

上面是一些关键的函数,比如RegisterThread()InitializeJVM(...)。继续看JavaMain(...)函数:

可以看到VM启动后,就是LoadMainClass(),然后通过GetStaticMethodID,来执行main方法。

上面就是JavaMain(...)的一个大概的执行过程。接着可以重点看下InitializeJVM(...)这个函数:

在这里面,重点是CreateJavaVM(...)这个函数.查找下它的定义位置:

可以看到,在JDK的源代码里面并没有CreateJavaVM(...)的具体实现,它只是一个接口定义,而由传入的InvocationFunctions来进行具体的定义。这一点可以从Java的标准化文档中找到:

Java Native Interface Specification: 5 - The Invocation API

从文档中可以看到CreateJavaVM(...)是一个接口定义:

查找这个接口的定义位置:

看到java_md.c里面的实现,打开这个文件看下:

可以看到JNI_CreateJavaVM是从handle里面来,而handle是从LoadLibrary(...)里面来。这个LoadLibrary(...)函数的名字比较直观,可以想到是读取VM的native library,应该是跟各平台相关的。我下载的openjdk代码里没有具体实现,但是可以从hotspot的实现(HotSpot是标准的Java VM:GitHub - openjdk-mirror/jdk7u-hotspot )里面找到实现供参考:

这个dll_load是各平台各自实现的,比如我们可以看bsd平台的实现:

可以看到调用的就是平台标准的动态库调用dlopen。可以看一下相关的dlopen位置:

以上是对JVM的一个从入口到加载的简单分析。