Java基础:JVM运行机制

来源:互联网 发布:mac os 最好的版本 编辑:程序博客网 时间:2024/04/30 00:05

JVM定义:

  顾名思义,JVM就是Java虚拟机。它有自己完善的硬件架构,例如处理器、堆栈、寄存器等,还具有相应的指令系统。

JVM须知:

  1.  它是Java字节码执行的引擎;
  2.  它能够优化Java字节码,使之转换为更高效率的机器指令。
  3. JVM中类的装载是通过类加载器(ClassLoader)和它的子类来实现的。
  4. JVM屏蔽了于具体操作系统平台相关的信息,从而实现了Java跨平台运行。

JVM工作原理:

  1. 创建JVM装载环境和配置。
  2. 装载jvm.dll。
  3. 初始化jvm.dll。
  4. 调用JNIEnv实例装载并处理class类。
  5. 运行Java程序。      
JVM工作机制实例参考:
      

     一.jvm装入环境,jvm提供的方式是操作系统的动态连接文件.既然是文件那就一个装入路径的问题,java是怎么找这个路径的呢?当你在调用java test的时候,操作系统会在path下在你的java.exe程序,java.exe就通过下面一个过程来确定jvm的路径和相关的参数配置了.下面基于windows的实现的分析.

  首先查找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路径。

  然后装载jvm.cfg文件JRE路径+/lib+/ARCH(CPU构架)+/jvm.cfgARCH(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_CreateJavaVM和JNI_GetDefaultJavaVMInitArgs挂接到InvocationFunctions变量的CreateJavaVM和GetDefaultJavaVMInitArgs函数指针变量上。jvm.dll的装载工作宣告完成。

  三:初始化jvm,获得本地调用接口,这样就可以在java中调用jvm的函数了.

      四:调用InvocationFunctions->CreateJavaVM也就是jvm中JNI_CreateJavaVM方法获得JNIEnv结构的实例.

   五:运行java程序.

    java程序有两种方式一种是jar包,一种是class. 运行jar,java -jar XXX.jar运行的时候,java.exe调用GetMainClassName函数,该函数先获得JNIEnv实例然后调用java类java.util.jar.JarFileJNIEnv中方法getManifest()并从返回的Manifest对象中取getAttributes("Main-Class")的值即jar包中文件:META-INF/MANIFEST.MF指定的Main-Class的主类名作为运行的主类。之后main函数会调用java.c中LoadClass方法装载该主类(使用JNIEnv实例的FindClass)。main函数直接调用java.c中LoadClass方法装载该类。如果是执行class方法。main函数直接调用java.c中LoadClass方法装载该类。

然后main函数调用JNIEnv实例的GetStaticMethodID方法查找装载的class主类中

“public static void main(String[] args)”方法,并判断该方法是否为public方法,然后调用JNIEnv实例的

CallStaticVoidMethod方法调用该java类的main方法。

0 0
原创粉丝点击