JVM——结构
Java体系:
JDK(Java development Kit)包括:java程序设计语言,java虚拟机,java API类库。如图:
Java技术体系:Java Card(Applets),Java ME(Micro Edition),Java SE(Standard Edition),Java EE(Enterprise Edition)。
Jvm结构概念:
运行时数据区域(Runtime Data Areas)
Jvm定义了一组运行时数据区域,这些区域在Jvm运行程序时使用。一些区域在JVM启动的时候就被创建,在JVM关闭时销毁。还有些区域是每个线程所有的。线程启动时创建,线程结束时销毁。
pc 寄存器(Program Counter Register)
JVM支持多线程,每个线程都有自己的pc寄存器。如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址,如果是native的,这个计数器值则为空(Undefined)。
Jvm栈
虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表,操作栈,动态链接,方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈道出栈的过程。栈的局部变量主要存放一些基本类型的变量(int,short, long, byte, float, double, boolean, char),对象句柄(reference类型)和returnAddress类型。
本地方法栈(Native Method Stacks)
本地方法栈于虚拟机栈所发挥的作用非常相似,区别是虚拟机栈为虚拟机执行Java方法服务,本地方法栈则是为虚拟机使用到的Native方法服务。
Java堆(Heap)
Jvm有一个堆,所有Jvm中的线程共享这个堆。所有的类对象实例和数组都分配在堆上。Jvm堆在Jvm启动的时候被创建。Jvm提供一个垃圾收集者来管理堆。堆上的对象不需要程序员显式地销毁。堆可以是固定大小,也可以根据需要增加大小。堆可以是不连续的。
方法区域(Method Area)
所有Jvm中的线程共享这个区域,它用于存储已被虚拟机加载的类信息,常量,静态变量,即使编译器编译后的代码等数据。
运行时常量池(Runtime Constant Pool)
运行时常量池是方法区的一部分。Class文件中除了有类的版本,字段,方法,接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池。
Jvm结构说明:
1.每个Java虚拟机实例都有一个方法区以及一个堆,它们是由该虚拟机实例中所有线程共享的。
2.每个线程被创建时,都将得到自己的PC寄存器以及一个Java栈。任何线程都不能访问另一个线程的PC寄存器或者Java栈。
3.数据类型:基本类型和引用类型:
4.方法区:
1)对方法区数据的访问是线程安全的。
2)方法区的大小不必是固定的,虚拟机可以根据应用的需要动态调整。方法区也不必是连续的,方法区可以在一个堆(甚至是虚拟机自己的堆)中自由分配。虚拟机允许用户或者程序员指定方法区的初始大小以及最小和最大尺寸等。
3)方法区也可以被垃圾回收。
4)方法区中储存的信息:
- 这个类型的全限定名。
- 这个类型的直接超类的全限定名(除非这个类是java.lang.Object,它没有超类)
- 这个类型是类类型还是接口类型。
- 这个类型的访问修饰符(public,abstract或final的某个子集)
- 任何直接超接口的全限定名的有序列表。
- 该类型的常量池。
- 字段信息。
- 方法信息。
- 除了常量以外的所有类(静态)变量。
- 一个到类ClassLoader的引用。
- 一个到Class类的引用。
5.执行引擎
1)运行中Java程序的每一个线程都是一个独立的虚拟机执行引擎的实例。
2)JVM的指令集以栈为中心,而非以寄存器为中心,使得在那些只有很少的寄存器,或者寄存器很没有规律的机器上实现Java更便利。
PS:
1.Class类使得运行程序可以访问方法区中保存的信息(及反射的原理)。
2.数组是真正的对象,和其他对象一样,数组总是存储在堆中。
参考资料:
《深入理解java虚拟机》
《深入Java虚拟机》