运行时数据区域的简要总结:
1.程序计数器:
特性
线程私有,一个线程一个
功能
当前线程所执行的字节码行号显示器,虚拟机字节码解释器通过改变程序计数器的值来取下一条需要执行的字节码指令,常见的控制语句都需要它来完成
执行java方法,代表的是字节码指令的地址
执行native方法 计数器值置空
异常:
唯一一个没有规定任何OutOfMemoryError情况的区域
2.java虚拟机栈
特性:
同样是线程私有 生命周期与线程相同
功能:
描述java方法执行的内存模型,每个方法在执行时会创建一个栈帧,存储方法所用到的局部变量表,操作数栈,动态链接,方法出口等信息,每一个方法的执行的过程都对应着一个栈帧在虚拟机中从入栈到出栈的完整过程
异常:
虚拟机中有固定长度的栈和可以动态扩展的栈,如果线程请求的栈深度大于虚拟机锁允许的栈深度,则会报stackOverFlowError(栈溢出)异常,如果动态扩展时候无法申请到足够的内存,就会抛出outOfMemorryError异常,(内存溢出)
3.本地方法栈
特性:同虚拟机栈
功能:执行本地native方法
异常:同虚拟机栈
4.java堆
特性:虚拟机管理内存中最大的一块
所有线程共享
可以处在物理上不连续的空间中
是垃圾回收器管理的主要区域,因此也称GC堆
功能:
存放对象实例,基本上所有的对象都在堆里(由于现在新的JIT编译器的发展与逃逸技术成熟,栈上分配,标量替换等技术也可以使得对象不一定非得放在堆里)
内存区域中会为了更好的回收内存,划分新生代和老年代区域,为了配合GC的分代回收算法,便于更好的回收内存,也会为不同的进程分配不同的多个线程私有的分配缓冲区,不管如何划分,存储的对象始终没变
异常:
如果堆中没有内存完成实例分配,并且堆也无法动态扩展的时候,会报OutOfMemorryError异常
5.方法区
特性
与java堆相同,是各个线程共享的内存区域,其大小既可以选择固定大小,也可以选择动态扩展,并且还可以选择不实现垃圾收集
该区域的回收目标是:针对于常量池的回收和类型的卸载
功能
用于存储已被虚拟机加载的类的信息,常量,静态变量,即时编译器编译后的代码等数据 又称为non-heap(非堆)--因为虚拟机规范把它描为堆的一个逻辑部分,叫non-Heap应该是要与堆区分开
异常
一旦方法区无法满足内存分配需求的时候-----OutOfMemorrryError
6.运行时常量池
特性
区别于class文件中的常量池有一个特性就是动态型性,也就是该区域并非存放着Class文件预置入常量池中的内容,运行期间也可能将新的常量放入池中,典型的是String.intern()
功能
用于类加载后, 存放Class文件信息中的常量池,(用于存放编译期生成的各种字面常量和符号引用)
异常
由于是方法区的一部分,定然受方法区限制,
OutOfMemorryError
7.直接内存
在JDK1.4中采用了基于通道和缓冲区的I/O方式,可以使用native函数直接分配堆外内存,然后再在堆中存储一个DirectByteBuffer对象作为这一块区域的引用进行操作
优点:避免了java堆和native堆的来回复制,提升性能
缺点:内存分配不受java堆的控制,只受本机总内存以及处理器寻址空间的限制,服务器管理员在配置虚拟机参数的时候,经常忽略掉了直接内存这一块,使得各个内存的区域总和大于物理内存限制,从而导致动态扩展时候出现了OOM异常