Java内存区域与内存溢出异常

运行时数据区域

在这里插入图片描述

程序计数器 (Program Counter Register)

  • 程序计数器可以看作是当前线程所执行的字节码的行号的指示器,占用较小的内存空间。此内存区域是唯一一个在《Java虚拟机规范》中没有规定任何OutOfMemoryError情况的区域。
  • 在Java虚拟机的概念模型里,其中的字节码解释器就是通过操作这个计数器的值来选取下一行要执行的代码,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
  • 每个线程都拥有一个独立的程序计数器,以应对多线程之间计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。

Java虚拟机栈 (Java Virtual Machine Stack)

  • Java虚拟机栈也是线程私有的,它的生命周期与线程相同。
  • 每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧(Stack Frame)用于存储 局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
  • 该区域会出现两种异常
    StackOverflowError异常代表线程请求的栈深度大于虚拟机所允许的深度;简单描述就是需要加载的方法太多内存不够用。
    OutOfMemoryError异常,当Java虚拟机栈容量可以动态扩展且栈扩展时无法申请到足够的内存时抛出。当开启动态扩展之后还不够用就会抛出这个异常。

本地方法栈(Native Method Stacks)

  • 本地方法栈与虚拟机栈所发挥的作用是非常相似的,其区别只是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的本地(Native)方法服务。
  • 《Java虚拟机规范》对本地方法栈中方法使用的语言、使用方式与数据结构并没有任何强制规定,因此具体的虚拟机可以根据需要自由实现它,甚至有的Java虚拟机(譬如Hot-Spot虚拟机)直接就把本地方法栈和虚拟机栈合二为一。与虚拟机栈一样,本地方法栈也会在栈深度溢出或者栈扩展失败时分别抛出StackOverflowError和OutOfMemoryError异常。

Java堆(Java Heap)

  • Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,Java世界里“几乎”所有的对象实例都在这里分配内存。
  • Java堆是 垃圾收集器管理的内存区域 也被称作“GC堆”(Garbage CollectedHeap)。经常会被人分为“新生代”“老年代”“永久代”“Eden空间”“From Survivor空间”“To Survivor空间”等名词,但是到了今天,垃圾收集器技术与十年前已不可同日而语,HotSpot里面也出现了不采用分代设计的新垃圾收集器,再按照上面的提法就有很多需要商榷的地方了。
  • 线程共享的Java堆中可以划分出多个线程私有的分配缓冲区,用来提升对象分配时的效率。不过无论从什么角度,无论如何划分,都不会改变Java堆中存储内容的共性,无论是哪个区域,存储的都只能是对象的实例,将Java堆细分的目的只是为了更好地回收内存,或者更快地分配内存。
  • Java堆既可以被实现成固定大小的,也可以通过参数 -Xmx-Xms设定。
  • 如果在Java堆中没有内存完成实例分配,并且堆也无法再扩展时,Java虚拟机将会抛出OutOfMemoryError异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值