第五章 java虚拟机

来源:互联网 发布:古天乐小学 知乎 编辑:程序博客网 时间:2024/05/16 12:19

5.1  java虚拟机是什么

  抽象规范

  一个具体的实现

  一个运行的虚拟机实例

5.2 java虚拟机的生命周期

 

当启动一个java程序时 一个虚拟机实例就诞生了,当该程序关闭退出,这个虚拟机实例也就随之消亡。

java虚拟机内部有两种线程:守护线程和非守护线程。守护线程通常是由虚拟机自己使用的,比如垃圾回收机制,不过java 程序也可以把它创建的任何线程标识为守护线程,而java程序中初始线程mian()的那个是非守护线程。

 

只要还有非守护线程在运行,那么这个java程序也继续运行。当该程序所有非守护线程都终止市,虚拟机实例将自动退出。

 

5.3 java虚拟机的体系结构

 

  

java虚拟机的内部体系结构图

每一个java虚拟机都有一个类装载器子系统,它根据给定的全限定名来装入类型(类或接口)。同样,每个java虚拟机都有一个执行引擎,它负责执行那些包含在被装载类的方法中的指令。

 

某些运行时数据区是由程序中所有线程共享的,还有一些则只能由一个线程拥有。每个java虚拟机实例都有一个方法区以及一个堆,他们是由该虚拟机实例中所有线程共享的。当虚拟机装载一个class文件时,它会从这个class文件包含的二进制数据中解析类型信息,然后它把这些类型信息放到方法区中。当程序运行时,虚拟机会把所有该程序在运行时创建的对象都放到堆中

 

 

 当每一个新线程被创建时,它都将得到它自己的pc寄存器(程序计数器)以及一个java栈。如果线程正在执行一个java方法(非本地方法),那么pc寄存器的值总是只是下一条将被执行的指令,而它的java栈则总是存储该线程中java方法调用的状态-----包括它的局部变量,被调用时传进来的参数,它的返回值以及运算的中间结果等等。而本地方法调用的状态则是以某种依赖于具体实现的方式存储在本地方法栈中,也可能是在寄存器或者其他某些与特定实现的相关内存中。

 

java虚拟机没有寄存器,其指令是使用java栈来存储中间数据,这样设计的原因是为了保持java虚拟机的指令集尽量紧凑,同时也便于java虚拟机在那些只有很少通用寄存器的平台上实现,另外,java虚拟机的这种基于栈的体系结构,也有助于运行时某些虚拟机实现的动态编译器和即时编译器的代码优化。

 

注意:任何线程都不能访问另一个线程的pc寄存器或者是java

 

数据类型:java虚拟机中数据类型可以分为两种:基本类型和引用类型。基本类型的变量只有原始值,而引用类型的变量持有引用值。引用值是指对某一个对象的引用,而不是该对象本身。

 

boolean以外,java语言的基本类型构成了java虚拟机的数值类型。虚拟机中的数值类型分为两种:整数类型(byteshortintlongchar)以及浮点类型(floatdouble),和java语言一样,java虚拟机的基本类型的值域在任何地方都是一致的。比如 不管底层的平台是什么,一个long在任何虚拟机中总是64位二进制补码表示的有符号整数。

Java虚拟机的引用类型被统称为“引用”,有三种引用类型:类类型,接口类型以及数组类型。他们的值都是对动态创建对象的引用。类类型的引用被统称为对类实例的引用。接口类型的引用是对实现了该接口的某一个类实例的引用,数组类型的值是对数组对象的引用。还有一个特殊的引用值null,它表示该引用变量没有引用任何对象。

 

类装载器子系统(在java虚拟机中,负责查找并装载类型的那一部分被成为类装载子系统)

Java虚拟机有两种类装载器:启动类装载器和用户自定义装载器。前者是java虚拟机实现的一部分,后者则是java程序的一部分。由不同的类装载器装载的类将被放在虚拟机内部的不同的命名空间中。

类装载器子系统除了要定位和导入二进制的class文件外,还必须负责验证被导入类的正确性。为类变量分配并初始化内存。以及帮助解析符号引用。这些动作必须严格按一下顺序进行:

1)   装载----查找并装载类型的二进制数据

2)   连接----执行 验证(确保被导入类型的正确性),准备(为类变量分配内存,并将其初始化为默认值) 以及解析(把类型中的符号引号转换成为直接引用)

3)   初始化---把类变量初始化为正确的初始值