Java内存区域与内存溢出异常
运行时数据区域
1.程序计数器(线程私有)
当前线程执行的字节码的行号指示器。
Java虚拟机的多线程通过线程轮流切换并分配处理器执行时间的方式来实现,一个处理器或者多核处理器的一个内核只会执行一条线程,每条线程需要一个独立的程序计数器
- 如果线程在执行一个普通的Java方法,计数器记录正在执行的虚拟机字节码指令的地址;
- 如果线程正在执行一个Native方法,计数器的值为空;
- 此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
2.Java虚拟机栈(线程私有)
虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时会创建一个栈帧用于存储局部变量表,操作数栈,动态链接、方法出口等信息。每个方法的执行过程,就对应一个栈帧在虚拟机栈中的入栈和出栈。
1).局部变量表
- 基本数据类型(boolean、byte、char、short、int、long、double)
- 对象引用(reference类型)对象本身、对象起始地址的引用指针、指向一个对象的句柄、其他与此对象相关的位置
- returnAddress类型 指向一条字节码指令的地址
2).两种异常状态
StackOverflowError异常:线程请求的栈深度大于虚拟机所允许的深度
OutOfMemoryError异常:虚拟机栈可以动态扩展,如果扩展的时无法申请到足够的内存
3.本地方法栈
作用与Java虚拟机栈相似:Java虚拟机栈为Java方法服务,抛出异常同虚拟机栈。
被动方法栈为Native方法服务
4.Java堆
被所有的线程共享的一块内存区域,算是虚拟机所管理的内存中最大的一块,带区域主要存储对象实例,是主要垃圾收集器管理的区域。
如果堆中没有内存完成实例分配,就会抛出OutOfMemoryError异常。
5.方法区
各个线程共享区域,用于存储已被虚拟机加载的类信息、常量、静态常量、即时编译器编译后的代码等数据。
6.运行时常量池
运行时常量池方法区的一部分
- Class文件存放类的版本、字段、方法、接口等描述信息外,还有常量池,常量池存放编译器生成的各种字面量和符号引用,这部分内容在类加载后进入方法区的运行时常量池存放。
- Java虚拟机对Class文件的每一部分的格式要求都有严格的规定。
- 运行常量池Java虚拟机规范没有任何细节的要求。
- 运行常量池中保存Class文件中描述的符号引用,翻译出来的直接引用也会存储在运行时常量池。
- 运行时常量池具有动态性,不要求常量一定要在编译器产生,并非置入Class文件中常量池的内容才能进入方法区运行时常量区,运行期间也可以将常量放在运行常量池中