Java内存区域与内存溢出异常(一)

  博主本来买了一本《深入理解java虚拟机》,但是一直没有时间看,今天去面试的时候,面试官问到了java内存溢出的相关问题,于是打算啃这本书。

  首先看看java虚拟机运行时所管理的几个数据区,如下图所示:


JVM运行时数据区
图1. JVM运行时数据区

  总的来说,JVM运行时数据区分为两大类:线程共享区和线程私有区。其中,线程共享区是随着JVM的启动而创建的,而线程私有区是随着用户线程的启动而创建的。


线程私有区

1. 程序计数器(Program Counter Register)

  程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。

  java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,所以任意时刻,一个处理器都只会执行一条线程中的指令。为了线程切换后能够恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,程序计数器与程序计数器之间互不影响,独立存储。

  如果线程正在执行的是一个java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果是一个Native方法(Native方法指不是由java代码写的方法,比如用C语言写的,但是在Java里调用),这个计数器的值为空(Undefined)。

  注意:这个内存区域是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

2. Java虚拟机栈

  虚拟机栈的生命周期和线程的生命周期相同。

  虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数帧、动态链接和方法出口等信息。每一个方法从调用直到执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程

  局部变量表存放了各种基本数据类型、对象引用和returnAddress类型(指向了一条字节码指令的地址)。其中,64位长度的long和double型数据会占用2个局部变量空间(Slot),其余的都只占1个。需要注意的是:局部变量表所需的内存空间在编译期间就完成了分配,进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,而且在方法运行期间是不会改变大小的

  虚拟机栈这个内存区域里,如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverFlowError异常;如果虚拟机栈可以动态扩展,而在扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。

3. 本地方法栈

  作用和虚拟机栈一样,只不过本地方法栈为Native方法服务。有的虚拟机也把本地方法栈和虚拟机栈合二为一。抛出异常的情况也和虚拟机栈一样。


线程共享区

1. Java堆(Java Heap)

  对于大多数应用来说,Java堆是Java虚拟机所管理的内存中最大的一块,在Java虚拟机启动时创建。所有的对象实例以及数组都要在堆上分配。Java堆有时也叫GC堆(Garbage Collected Heap)。Java堆只需要逻辑上连续即可,不需要连续的物理内存空间。

  如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,会抛出OutOfMemoryError异常。

2. 方法区

  用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

  方法区无法申请到内存时抛出OutOfMemoryError异常。

2.1 运行时常量池(Runtime Constant Pool)

  运行时常量池是方法区的一部分,里面存放编译期生成的各种字面量符号引用,不过,运行期间产生的新的常量也可能被放入池中,比如String类的intern()方法。

  常量池无法申请到内存时抛出OutOfMemoryError异常。

  (关于符号引用:符号引用是一个字符串,它给出了被引用的内容的名字并且可能会包含一些其他关于这个被引用项的信息——这些信息必须足以唯一的识别一个类、字段、方法。这样,对于其他类的符号引用必须给出类的全名。对于其他类的字段,必须给出类名、字段名以及字段描述符。对于其他类的方法的引用必须给出类名、方法名以及方法的描述符。)

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值