Java虚拟机生命周期和体系结构

来源:互联网 发布:织梦cms教程pdf 编辑:程序博客网 时间:2024/05/07 06:00

1. Java虚拟机的生命周期 

    一个运行时的Java虚拟机负责运行一个Java程序。当启动一个Java程序时,一个虚拟机实例也就诞生了。当程序关闭退出,这个虚拟机实例也就随之消亡。如果在同一台计算机上同时运行三个Java程序,将得到三个Java虚拟机实例。每个Java程序都运行于它自己的Java虚拟机实例中。 

    Java虚拟机实例通过调用某个初始类的main()方法来运行一个Java程序。而这个main()方法必须是publi
c static的,返回值为void,并且接受一个String[]数组作为参数。任何拥有这样一个main()方法的类都可以作为Java程序运行的起点。告诉Java虚拟机要运行的Java程序中初始类的名字,整个程序将从它的main()方法开始运行。 

    Java程序初始类中的main()方法,将作为该程序初始线程的起点,任何其他的线程都是由这个初始线程启动的。 

  Java虚拟机内部有两种线程:守护线程和非守护线程。守护线程通常是由虚拟机自己使用的,比如执行垃圾收集任务的线程。 但是,Java程序也可以把它创建的任何线程标记为守护线程。而Java程序中的初始线程-就是开始于main()的那个是非守护线程。 

   只要还有任何非守护线程在运行,那么这个Java程序也在继续运行(虚拟机仍然存活)。当程序中的所有的非守护线程都终止时,虚拟机实例自动退出。假如安全管理器允许,程序本身也能够通过调用Runtime类或者System类的exit()方法退出。 


2. Java虚拟机的体系结构
 

   在Java假虚拟机规范中,一个虚拟机实例的行为时分别按照子系统、内存区、数据类型以及指令这几个术语来描述的。这些组成部分一起展示了抽象的虚拟机的内部抽象体系结构。 

 

 

 


当Java虚拟机运行一个程序时,它需要内存来存储多个东西、例如,字节码、从已装载的class文件中得到的其他信息、对象、方法参数、返回值、局部变量以及运算的中间结果等等,Java虚拟机把这些东西组织到几个"运行时数据区"中,以便于管理。 

   尽管这些"运行时数据区"都会以某种形式存在于每一个Java虚拟机实现中,但是规范对它们的描述却是相当抽象的。这些运行时数据区结构上的细节,大多数由具体实现的设计者决定。 
  
   某些运行时数据区是由程序中所有线程共享的,还有一些则只能由一个线程拥有,每个Java虚拟机实例都有一个方法区以及一个堆,它们是由该虚拟机实例中所有线程共享的。当虚拟机装载一个class文件时,它会从这个class文件包含的二进制数据中解析类型信息。然后,它把这些类型信息放到方法区中。当程序运行时,虚拟机会把所有该程序在运行时创建的对象都放到堆中。 

 

 

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

  Java栈是由许多栈帧组成的,一个栈帧包含一个Java方法调用的状态。当线程调用一个Java方法时,虚拟机压入一个新的栈帧到该线程的Java栈中:当该方法返回时,这个栈帧被从Java栈中弹出被抛弃。    

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

   Java虚拟机为每一个线程创建的内存区,这些内存区域是私有的。任何线程都不能访问另一个线程的PC寄存器或者Java栈。 


如图展示了一个虚拟机实例的快照,它有三个线程正在执行。线程1和线程2都正在执行Java方法,而线程3则正在执行一个本地方法。Java栈都是向下生长的,而栈顶都显示在图的底部。当前正在执行的方法的栈帧以浅色表示,对于一个正在运行Java方法的程序而言,它的PC寄存器总是指向下一条将被执行的指令。 

原创粉丝点击