HotSpot VM运行时系统为HotSpot JIT编译器和垃圾收集器提供服务和通用API,同时还为VM提供启动线程管理JNI(Java本地接口)等基本功能。HotSpot VM运行时环境担当许多职责,具体如下:

1、命令行选项

  通过命令行选项来配置HotSpot VM,相当于HotSpot VM的配置文件,主要包括选择哪个JIT编译器、何种垃圾收集器、Java Heap的大小等。命令行选项主要有3类:

1.1、标准选项(Standard Option)

  标准选项是Java Virtual machine Specification要求所有Java虚拟机都实现的选项,它们在发行版之间保持稳定,但也可能在后续的发行版中被废除。

1.2、非标准选项(Nonstandard Option)

  非标准选项(以-X为前缀)不保证、也不强制所有JVM实现都必须支持,它可能未经通知就在Java SDK发行版之间发生更改。

1.3、非稳定选项(Developer Option)

  非稳定选项通常是为了特定需要而对JVM的运行进行校正,并且可能需要有系统配置参数的访问权限。与非标准选项一样,非稳定选项也可能不经通知就在发行版之间发生变动。

2、VM生命周期

  HotSpot VM运行时系统负责启动和停止HotSpot VM。启动HotSpot VM的组件式启动器。HotSpot VM有若干个启动器。Unix/Linux上最常用的是java,Windows上是java和javaw。也可以通过JNT接口(JNI_CreateJavaVM)启动内嵌的JVM,另外还有一个网络启动器Javaws(Java Web Start)。

  启动器启动HotSpot VM时会执行一系列操作。步骤概述如下:

  (1)解析命令行选项

  (2)设置堆的大小和JIT编译器

    如果命令行没有明确设置堆的大小和JIT编译器,启动器则通过自动优化进行设置。

  (3)设定环境变量如:LD_LIBRARY_PATH和CLASSPATH

  (4)如果命令行有-jar选项,启动器则从指定JAR的manifest中查找Main-Class,否则从命令行读取Main-Class

  (5)使用标准Java本地接口(Java Native Interface,JNI)方法JNI_CreateJavaVM在新创建的线程中创建HotSpot VM

  (6)一旦创建并初始化号HotSpot VM,就会加载Java Main-Class,启动器也会从Java Main-Class中取得Java main方法的参数

  (7)HotSpot VM通过JNI方法CallStartVoidMethod调用Java main方法,并将命令行选项传给它

3、VM类加载

  (1)类加载阶段

    对给定的Java类或者接口,类加载时会依据她的名字找到Java类的二进制字节流,定义Java类,然后创建代表这个类或者接口的java.lang.Class对象。HotSpot VM必须先加载它的所有超类和超接口。如果类的继承层次有错,HotSpot VM则会抛出ClassCircularityError。

    链接的第一步是验证,检查类文件的语义、常量池符号以及类型。第二步是准备,它会创建静态字段,初始化为标准默认值,以及分配方法表。

    如:int的标准默认值为0;public static int value=123,准备阶段将其初始化为0而不是123,value=123的赋值操作在内构造器<clinit>()中。

      public static final int value=123,编译时会为value在字段属性表中生成ConstantValue,从而在准备阶段就被初始化成123。

    初始化类,运行类构造器。初始化类需要首先初始化超类(不会初始化超接口)。

  (2)类加载器委派

    Java SE类加载器的层级查找顺序为启动类加载器扩展类加载器系统内加载器系统类加载器是默认的应用程序类加载器,它加载Java类的main方法并从classpass上加载类。应用程序类加载器可以是Java SE系统自带的类加载器,或者由应用程序开发人员提供。扩展类加载器则由Java SE系统实现,它负责从JRE(Java Runtime Environment)的lib/ext目录下加载类。

  (3)启动类加载器

    启动类加载器是由HotSpot VM实现的,负责加载BOOTCLASSPATH路径中的类,如包含Java SE类库的rt.jar。

  (4)类型安全

    Java类或接口的名字为全限定名(包括包名)。Java的类型由全限定名何类加载器唯一确定。

  (5)HotSpot类元数据

    类加载时,HotSpot VM会在永久代创建类的内部表示instanceKlass或arrayKlass。instanceKlass应用了与之对应的java.lang.Class实例,后者是前者的Java镜像。HotSpot VM内部使用称为klassOop的数据结构访问instanceKlass。后缀“Oop”表示普通对象指针,所以klassOop是应用java.lang.Class的HotSpot内部抽象,它是指向Klass(与Java类对应的内部表示)的普通对象指针。

  (6)内部的类加载数据

    类加载过程中,HotSpot VM维护了3张散列表。SystemDictionary包含已加载的类,它将建立类名/类加载器(包括初始类加载器和定义类加载器)与klassOop对象之间的映射。muqian有在安全点事才能移除SystemDictionary中的元素。Placeholder-Table包含当前正在加载的类,它用于检查ClassCircularityError,多线程类加载器并行加载类时也会用到它。LoaderConstraintTable用于追踪类型安全检查的约束条件。这些散列表都需要加锁保证访问安全,在HotSpot VM中,这个锁称为SystemDictionary_lock。通常,HotSpot VM借助类加载器对象锁对加载类的过程进行序列化。

4、字节码验证

  在链接时必须进行字节码验证以保证类型安全。

5、类数据共享

  类数据共享的首要目的是减少启动时间,同时还可以节省内存空间。

6、解释器

  HotSpot VM解释器是一种基于模板的解释器。JVM启动时,HotSpot VM运行时系统利用内部TemplateTable中的信息在内存中生成解析器。TemplateTable包含于每个字节码对应的机器代码,每个模板描述一个字节码。

7、异常处理

  当与Java的语义约束冲突时,Java虚拟机会用异常通知程序。异常处理由HotSpot VM解释器、JIT编译器和其他HotSpot VM组件一起协作实现。异常处理主要有两种情形,同一方法中抛出和捕获异常;由调用方法捕获异常。异常可以由抛出字节码、VM内部调用返回、JNI调用返回或Java调用返回所引发。

8、线程管理

  HotSpot VM的线程模型中,Java线程(java.lang.Thread实例)被一对一映射为本地操作系统线程。HotSpot VM内部以C++类JavaThread的实例表示java.lang.Thread实例,它包含其他的线程状态追踪信息。当java.lang.Thread启动时,HtoSpot VM创建与之相关联的JavaThread和OSThread对象(代表操作系统线程),最后是本地线程,依据线程关联是的参数,反射调用Thread类构造函数的Java代码,从而创建该对象。终止线程会释放所有已分配的资源,并从已知线程列表中移除JavaThread,然后调用OSThread和JavaThread的析构函数,当它的初始启动方法完成时,最终停止运行。

05-27 10:13