虚拟机是由一系列规范来定义一个抽象的计算机。所以要运行一个java程序,必须是一个符合该规范的具体实现。
java虚拟机一般有三种说法:
1 一个具体的实现,
2 一个运行的虚拟机实例,
3 抽象规范
JVM的职责就是负责一个java程序。(一个JVM对应一个java程序)既一个javaAPP启动,一个JVM的实例也就诞生了。程序退则JVM亡。如果一个OS上面运行三个javaAPP则产生三个JVM实例。每个javaAPP独立于对应的JVM中。
javaAPP都将以main()作为起点,而其他线程则以初始线程开启。在JVM里面有两中线程:守护线程和非守护线程。守护线程通常都是由JVM自己使用的,比如垃圾收集任务的线程。但是java程序也可以把任何线程标记为守护线程。而main()入口线程是非守护线程。
JVM 以任何非守护线程结束而结束。如果没有main()方法,没有创建其他线程,则main()方法退出时,JVM实例销毁。
一个虚拟机实例的行为分别按照子系统,内存区,数据类型以及指令这几和术语来描述,这些组成部分一起展示了抽象的JVM内部体系结构。值得注意的是,虽然对JVM着严格的规范,但是规范中并未对JVM内部的体系结构强制规定。更多的是为了严格定义这些实现的外部特征。
下面简单介绍下JVM的执行过程如图:
每个java虚拟机都有一个类装载器子系统,它根据给定的全限定名来装入类型(类或者接口)。同样每个java虚拟机都有一个执行引擎,它负责执行那些包含在被装载类的方法中的指令。当JVM在运行一个java程序时,它需要内存来存储许多东西,如字节码,从已装载的class文件得到的其他信息,程序创建的对象,传递给方法的参数,返回值,局部变量,以及运算的中间结果等等,java虚拟机将这些东西都组织到几"运行时数据区"中。以便于管理。
尽管这些“运行时数据区”都会以某种形式存在每一个java虚拟机实现中,但规范对它的描述却是相当的抽象,这些运行时数据区上的细节,大多由具体实现的设计者决定。
运行时数据区是所有线程共享的,有的只能由一个线程拥有,每个JVM实例只能有一个方法区以及一个堆。它们是由虚拟机实例中所有线程共享的。当虚拟机装载一个class时,它会从class文件包含的二进制数据中解析类型数据,放到方法区中,当程序运行时虚拟机会把程序正在运行时创建的对象都放到堆中。当每一个线程被创建时,它都会得到它的PC寄存器(程序计数器)以及一个java栈。如果java程序正在执行的是一个java方法(非本地方法),那么PC寄存器的值总是指示下一条将被执行的指令,而它的java栈总是存储该线程中java方法调用的状态,包括它的局部变量,被调用时传进来的参数,返回值,以及运算中间结果。
java栈是由许多栈帧组成的,一个栈帧包括一个java方法调用的状态。当线程调用一个java方法时。虚拟机压入一个新的栈帧到该线程的java栈中:当该方法返回时,这个栈帧从java栈中弹出并抛弃。