JVM启动流程

JVM是Java程序运行的环境,同时是一个操作系统的一个应用程序进程,因此它有自己的生命周期,也有自己的代码和数据空间。

JVM体系主要分为三个子系统和两大组件,分别是:类装载器子系统、执行引擎子系统和GC子系统,组件是内存运行数据区域和本地接口。

JVM工作是指操作系统装入JVM,是通过JDK中的java.exe来完成,通过下面4步来完成JVM环境。

1.创建JVM装载环境和配置

2.装载JVM.dll

3.初始化JVM获得JNIEnv接口

4.找到main()方法并运行

过程如下图:

JVM启动流程_第1张图片

一.JVM装入环境,JVM提供的方式是操作系统的动态连接文件

既然是文件那就有一个装入路径的问题,Java是怎么找到这个路径的呢?

当你在调用Java test的时候,操作系统会在path下找你的java.exe程序,java.exe就可通过下面一个过程来确定JVM的路径和相关的参数配置了,下面基于Windows的的实现的分析:

1、首先查找jre路径,Java是通过GetApplicationHome api来获得当前的Java.exe绝对路径,c:\j2sdk1.4.2_09\bin\Java.exe,那么它会截取到绝对路径c:\j2sdk1.4.2_09\,判断c:\j2sdk1.4.2_09\bin\Java.dll文件是否存在,


  如果存在就把c:\j2sdk1.4.2_09\作为jre路径,


  如果不存在则判断c:\j2sdk1.4.2_09\jre\bin\Java.dll是否存在,如果存在这c:\j2sdk1.4.2_09\jre作为jre路径.如果不存在调用GetPublicJREHome查HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\“当前JRE版本号”\JavaHome的路径为jre路径。


2、然后装载JVM.cfg文件JRE路径+\lib+\ARCH(CPU构架)+\JVM.cfg ,ARCH(CPU构架)的判断是通过Java_md.c中GetArch函数判断的,该函数中windows平台只有两种情况:WIN64的‘ia64’,其他情况都为‘i386’。以我的为例:C:\j2sdk1.4.2_09\jre\lib\i386\JVM.cfg.主要的内容如下:


-client KNOWN   
-server KNOWN   
-hotspot ALIASED_TO -client   
-classic WARN   
-native ERROR   
-green ERROR  
在我们的jdk目录中jre\bin\server和jre\bin\client都有JVM.dll文件存在,而Java正是通过JVM.cfg配置文件来管理这些不同版本的JVM.dll的.通过文件我们可以定义目前jdk中支持那些JVM,前面部分(client)是JVM名称,后面是参数,KNOWN表示JVM存在,ALIASED_TO表示给别的JVM取一个别名,WARN表示不存在时找一个JVM替代,ERROR表示不存在抛出异常.


  在运行Java XXX是,Java.exe会通过CheckJVMType来检查当前的JVM类型,Java可以通过两种参数的方式来指定具体的JVM类型,一种按照JVM.cfg文件中的JVM名称指定,第二种方法是直接指定,它们执行的方法分别是“Java -J”、“Java -XXaltJVM=”或“Java -J-XXaltJVM=”。如果是第一种参数传递方式,CheckJVMType函数会取参数‘-J’后面的JVM名称,然后从已知的JVM配置参数中查找如果找到同名的则去掉该JVM名称前的‘-’直接返回该值;而第二种方法,会直接返回“-XXaltJVM=”或“-J-XXaltJVM=”后面的JVM类型名称;如果在运行Java时未指定上面两种方法中的任一一种参数,CheckJVMType会取配置文件中第一个配置中的JVM名称,去掉名称前面的‘-’返回该值。CheckJVMType函数的这个返回值会在下面的函数中汇同jre路径组合成JVM.dll的绝对路径。如果没有指定这会使用JVM.cfg中第一个定义的JVM.可以通过set _Java_LAUNCHER_DEBUG=1在控制台上测试.


最后获得JVM.dll的路径,JRE路径+\bin+\JVM类型字符串+\JVM.dll就是JVM的文件路径了,但是如果在调用Java程序时用-XXaltJVM=参数指定的路径path,就直接用path+\JVM.dll文件做为JVM.dll的文件路径.

 

二:装载JVM.dll

通过第一步已经找到了JVM的路径,Java通过LoadJavaVM来装入JVM.dll文件,装入工作很简单就是调用Windows API 函数:

LoadLibrary 装载JVM.dll动态连接库,然后把JVM.dll中的导出函数JNI_CeateJavaVM和JNI_GetDefaultJavaVMInitArgs挂接到InvocationFunctions变量的CreateJavaVM和GetDefaultJavaVMInitArgs函数指针变量上。JVM.dll的装载工作宣告完成。

 

三:初始化JVM

初始化JVM,获得本地调用接口,这样就可以在Java中调用JVM的函数了,调用InvocationFunctions->CreateJavaVM也就是JVM中的JNI_CreateJavaVM方法获得JNIENV结构的实例。

 

四:运行程序

Java程序有两种运行方式,一种是jar包,一种是.class

运行jar包,通过命令java -jar XXX.jar运行的时候,java.exe调用GetMainClassName函数,该函数先获得JNIENV实例,然后调用Java类的java.util.jar.JarFileJNIENV中方法getMainfest()并从返回的Mainfest对象中获取getAttribute("Main-Class")的值即jar包中文件:META-INF/MANIFEST.MF指定的Main-class的主类名作为运行的主类。

之后会调用java.c中的LoadClass方法装载该主类(使用JNIENV实例的findClass)。

然后调用JNIENV实例的GetStaticMethodID方法查找装载的class主类中的"public static void main(String[] args)"方法。

你可能感兴趣的:(JVM启动流程)