这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战
内存区域
程序计数器
当前线程锁执行的字节码的行号指示器,分支,循环,跳转,异常处理,线程恢复都需要依赖这个计数器。
线程私有,为了线程切换后能够恢复到正确的执行位置。
- 方法类别
当正在执行的时Java方法,计数器记录的是正在执行的虚拟机字节码指令的地址
当前正在执行的Native方法,计数器值为空。
java虚拟机栈
线程私有;生命周期与线程相同;
当每个方法被执行,栈会同步创建一个栈帧用于存储局部变量表,操作数栈,动态连,方法出口等信息。 被调用是入栈,执行完毕出栈。
- 局部变量表
局部变量表存放编译期可知的各种基本数据类型,对象引用地址,字节码指令地址。
存储空间以局部变量槽表示。64位的long和double类型占用两个槽,其他的占用一个。
在编译期间,完成局部变量表的内存空间
当执行一个方法时,方法分配局部变量表空间的大小(变量槽的数量)是确定的。
- 异常
1.线程请求的深度大于栈的深度,StackOverflowError异常
2.栈的容量可以扩展(但是HotSpot是无法扩展的),无法申请足够内存会OutOfMemoryError异常
- jdk1.7之后
将永久代的字符串常量池和静态变量等移至堆中,其他的内容(主要是类型信息)存放到元空间
堆
堆时虚拟机管理的内存中最大的一块,线程共享。
唯一目的:存放对象实例
垃圾收集器管理的内存区域
从分配角度看,可以划分出多个线程私有的缓冲区,提升内存分配的效率
是可拓展的:-Xmx 和-Xms设定。
- 异常
当堆中无法再拓展但是还有未分配的对象,就会OOM异常。
方法区
线程共享:存储已被加载的类信息,常量,静态变量,即时编译器编译后的代码缓存等数据。
方法区,在JDK8以前,被称呼为永久代,JDK1.8 之后,称为元空间
垃圾回收针对常量池的回收和对类型的卸载。
- 异常
无法满足新的内存分配需求,跑出OOM异常。
运行常量池
是方法区的一部分。Class会将常量池表中的数据在类加载后存放在该区域中,包括字面量和符号引用。