运行时数据区域
虚拟机在执行java程序时,会将自己管理的内存区域划分为几个区域:程序计数器,虚拟机栈,方法区,Java堆,本地方法栈。
程序计数器,是内存中一块很小的区域,主要的工作是存储下一条指令的地址。这个区域的周期是线程级别的,每个线程都拥有一个程序计数器,执行的是java方法,里面存储的是一条字节码指令地址,如果运行的是Native方法(native方法是指由非java语言实现的方法),计数器为空。
java虚拟机栈,此内存区域也是线程私有的,主要用来描述java方法执行的内存模型,每个方法在执行过程中都会产生一个栈帧,栈帧由局部变量表,操作数栈,动态连接方法出口等信息,每个方法的执行和结束都伴随着栈帧的进栈和出栈。局部变量表中主要用来存放,基本数据类型的数据(int short long byte boolean char double float),和对象的引用(referrence类型,代表的可能是一个指向对象的指针变量,也可能是一个指向句柄的指针变量),内存空间在编译时就完成了内存空间的分配。可能产生的异常:当线程请求的深度超出了虚拟机所允许的深度会抛出StackOverflowerror异常,当存储数据时无法申请到足够的内存空间会抛出outofmemoryerror异常。
本地方法栈
本地方法栈和java虚拟机栈的发挥的作用相似,只是它是用来描述native方法的内存模型。
java堆
java堆是虚拟机中最大的内存区域,是线程共享的,主要就是用来存放对象实例和数组对象,也是GC主要管理的区域,也可以成为GC堆,GC收集器采用分代算法,内存区域可以分为新生代和老年代。在内存空间上是物理上不连续的内存空间,只是逻辑上的连续。在实例对象分配空间时,无法申请到更多的内存时会抛出outofmemoryerror异常。
方法区
方法区是一块线程共享的区域,用于存储加载的类信息,类静态变量,常量,编译后的代码等数据。方法区内存空间物理上是不连续的,还可以实现不垃圾回收。
运行时常量池
运行时常量池是方法区的一部分,Class文件除了由接口,方法,属性,版本外,还有编译时产生的常量和符号引用,这部分就存放在class文件的常量池中,在类加载是就会将class文件常量池中的内容存放在运行时常量池中。
对象的访问定位
对于对象的访问定位分为两种 1. 句柄方式。 2. 指针方式。
句柄方式:就是讲堆内存划分出一个句柄池和实例池,栈中的对象引用存储的是句柄池中对象的句柄地址,句柄中存储的指向对象实例数据的指针和指向对象的类型的指针。
直接指针方式:引用直接指向对象的实例数据和类型指针,类型指针指向对象类型。