java虚拟机在执行java程序的过程中把它管理的内存分为不同的几个数据区域。
运行时数据区:
划分如图所示:
1:程序计数器
注:这是唯一一个不会有OutOfMemoryError的区域
项目 |
内容 |
特点 |
比较小的一块内存区域 |
作用 |
当前所执行的字节码的行号指示器,字节码解释器通过这个计数器的值来选取下一条要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依靠这个计数器。 |
是否连续 |
是 |
线程私有 |
是 |
java方法和Native方法 |
如果正在执行java方法,则计数器记录正在执行的虚拟机字节码的指令的地址,如果是正在执行Native方法,则这个计数器的值为空(Undefined)。 |
是否会溢出 |
否 |
2:java虚拟机栈(栈内存)
项 目 |
内容 |
特 点 |
和线程的生命周期相同,是通常所说的栈内存 |
作 用 |
描述java执行的内存模型,每个方法在执行的时候都会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息。 |
是否连续 |
是 |
线程私有 |
是 |
是否会溢出 |
是,(*和OutOfMemoryError) |
栈溢出(*) |
线程请求的栈深度大于虚拟机所允许的深度。 |
内存溢出(OutOfMemoryError) |
拓展时无法申请到足够的内存。 |
3:本地方法栈
项 目 |
内容 |
特点 |
和java虚拟机栈发挥的作用相似 |
和java虚拟机栈的区别 |
java虚拟机栈执行java方法,本地方法栈执行native方法 |
是否连续 |
是 |
线程私有 |
是 |
是否会溢出 |
是,(*和OutOfMemoryError) |
栈溢出(*) |
线程请求的栈深度大于虚拟机所允许的深度。 |
内存溢出(OutOfMemoryError) |
拓展时无法申请到足够的内存。 |
4:java堆(堆内存)
项 目 |
内容 |
特点 |
java虚拟机管理内存中最大的一块,AKA:GC堆 |
作用 |
存放实例对象(对象以及数组都在堆上) |
组成 |
新生代,老年代(或者Eden空间,From Survivor空间,To Survivor空间) |
是否连续 |
可以不连续 |
线程私有 |
否 |
是否会溢出 |
是,(OutOfMemoryError) |
5:方法区
项 目 |
内容 |
特点 |
堆的一个逻辑部分,AKA:非堆(Non-Heap) |
作用 |
存储虚拟机的类信息,常量,静态变量,即时编译后的代码等数据。 |
是否连续 |
可以不连续 |
线程私有 |
否 |
是否会溢出 |
是,(OutOfMemoryError) |
其他内存区域:
1:运行时常量池
项 目 |
内容 |
特点 |
是方法区的一部分,受到方法区内存限制 |
作用 |
在类加载后保存Class文件中的的各种字面量和符号引用 |
线程私有 |
否 |
是否会溢出 |
是,(OutOfMemoryError) |
2:直接内存
项 目 |
内容 |
特点 |
不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存 |
是否会溢出 |
是,(OutOfMemoryError) |