上图先
1.1 程序计数器
介绍:
程序计数器是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器。
如果线程正在执行JAVA方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Native方法,这个计数器值为空。
问题:
此内存区域是唯一一个没有规定任务OutOfMemoryError情况的区域
1.2 JAVA虚拟机栈
介绍:
虚拟机栈描述的是JAVA方法执行的内存模型:每个方法在执行的同时都会创建一个帧栈用于存储局部变量表,操作数栈,动态链表,方法出口等信息。
我们平时所说的堆内存和栈内存指的就是现在讲的虚拟机栈,或者说是虚拟机栈中局部变量表的部分。
问题:
这个区域规定了两种异常状态:如果线程请求的栈深度大雨虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展时无法申请到足够内存则会抛出OutOfMemoryError异常。
1.3本地方法栈
介绍:
本地方法栈为Native方法服务。
问题:
和JAVA虚拟机栈异常相同,会抛出StackOverflowError异常和OutOfMemoryError异常
1.4 JAVA堆
介绍:
JAVA虚拟机所管理的内存中最大的一块就是JAVA堆内存。JAVA堆是被所有线程共享的一块内存区域,在虚拟机创建启动时创建。此内存唯一目的就是存放对象实例。
JAVA堆是垃圾收集器管理的主要区域,因此很多时候称为“”GC堆“”
问题:
如果在堆内存中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。
1.5 方法区
介绍:
方法区与JAVA堆一样,是个线程共享的内存区域,用于存贮已经被加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。
问题:
当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。
1.6 运行时常量池
介绍:
运行时常量池是方法区的一部分。用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。
问题:
当常量池无法再申请到内存时将抛出OutOfMemoryError异常。
1.7 直接内存
介绍:
直接内存并不是虚拟机运行时数据区的一部分,也不是JAVA虚拟机规范中定义的内存区域,但这部分内存也被频繁使用。
问题:
服务器管理员在配置虚拟机参数时,会根据实际内存设置-Xmx等参数信息,但经常忽略直接内存,使得各个内存区域总和大于物理内存限制(包括物理的和操作系统的限制),从而导致动态扩展时抛出OutOfMemoryError异常。