JVM自身的物理结构
![](http://images.cnitblog.com/blog/502866/201402/241532375103105.jpg)
JVM 生命周期
开始于一个main()方法,这个方法必须是公有、返回void、直接受一个字符串数组。
只要Java虚拟机中还有普通的线程(非守护线程)在执行,Java虚拟机就不会停止。如果有足够的权限,你可以调用exit()方法终止程序。
JVM 内存结构
![](http://images.cnitblog.com/blog/502866/201402/241535080657031.jpg)
JVM方法区
线程安全、
大小可变、
可被垃圾收集
方法区域存放了所加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息
类型信息
1)、类型的全名(The fully qualified name of the type)
2)、类型的父类型的全名(除非没有父类型,或者弗雷形式java.lang.Object)
3)、给类型是一个类还是接口(
class
or an
interface
)(Whether or not the type is a
class
)4)、类型的修饰符( public , private , protected , static , final , volatile ,transient等)(The typeís modifiers)
5 )、所有父接口全名的列表(An ordered list of the fully qualified names of any direct superinterfaces)
类型全名保存的数据结构由虚拟机实现者定义。除此之外,Java虚拟机还要为每个类型保存如下信息:
1)、类型的常量池(The constant pool for the type)
2 )、类型字段的信息(Field information)
3 )、类型方法的信息(Method information)
4)、所有的静态类变量(非常量)信息(All class ( static ) variables declared in the type, except constants)
5)、一个指向类加载器的引用(A reference to class ClassLoader)
6)、一个指向Class类的引用(A reference to
class
Class)
比如:
- Classloader 引用
- 运行时常量池
- 数值型常量
- 字段引用
- 方法引用
- 属性
- 字段数据
- 针对每个字段的信息
- 字段名
- 类型
- 修饰符
- 属性(Attribute)
- 针对每个字段的信息
- 方法数据
- 每个方法
- 方法名
- 返回值类型
- 参数类型(按顺序)
- 修饰符
- 属性
- 每个方法
- 方法代码
- 每个方法
- 字节码
- 操作数栈大小
- 局部变量大小
- 局部变量表
- 异常表
- 每个异常处理器
- 开始点
- 结束点
- 异常处理代码的程序计数器(PC)偏移量
- 被捕获的异常类对应的常量池下标
- 每个方法
JVM 堆
它是
JVM
用来存储对象实例以及数组值的区域,可以认为
Java
中所有通过
new
创建的对象的内存都在此分配,
Heap
中的对象的内存需要等待
GC
进行回收。
堆被用来在运行时分配类实例、数组。不能在栈上存储数组和对象。因为栈帧被设计为创建以后无法调整大小。栈帧只存储指向堆中对象或数组的引用。
JVM栈
JVM栈是线程私有的,每个线程创建的同时都会创建JVM栈,JVM栈中存放的为当前线程中局部基本类型的变量(java中定义的八种基本类型:boolean、char、byte、short、int、long、float、double)、部分的返回结果以及Stack Frame,非基本类型的对象在JVM栈上仅存放一个指向堆上的地址
每个线程拥有自己的栈,栈包含每个方法执行的栈帧。栈是一个后进先出(LIFO)的数据结构,因此当前执行的方法在栈的顶部。每次方法调用时,一个新的栈帧创建并压栈到栈顶。当方法正常返回或抛出未捕获的异常时,栈帧就会出栈。除了栈帧的压栈和出栈,栈不能被直接操作。所以可以在堆上分配栈帧,并且不需要连续内存。
每个栈帧包含:
-
- 局部变量数组
- 返回值
- 操作数栈
- 类当前方法的运行时常量池引用