浅谈JVM中的OutOfMemoryError和stackOverflowError

一、 JVM中区域的划分

Java虚拟机在执行java过程中会把它所管理的内存划分为若干个不同的数据区域。

1、程序计数器

当前线程所执行的字节码的行号指示器。那个多线程情况下每个线程都有一个程序计数器。由此可以看出程序计数器是线程私有的。内存区域是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

2、Java虚拟机

线程私有的,方法在执行时创建一个帧栈用于存储局部变量表,操作数栈,动态链接,方法出口等信息
比较官方的说法是在Java虚拟机规范中,1、如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;2、如果虚拟机栈可以动态扩展(大部分都可以动态扩展)如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。
一般这里重点可以说当递归调用方法, 递归的深度太大,超过栈的所允许的最大深度时候, 就会抛出StackOverflowError

3、本地方法栈

服务于虚拟机使用到的Native方法。
本地方法栈也会抛出StackOverflowError和OutOfMemoryError异常。

4、Java堆

存放对象实例, 内存中最大一块,存放对象实例。线程共享
假如不断强引用创建对象, 会出现OutOfMerroryError异常。

5、方法区

线程共享的内存区域,存储已被虚拟机加载的类信息、常量、静态变量,即时编译器编译后的代码等数据。
方法区可以不进行垃圾回收机制,垃圾收集行为在这个区域是比较少出现的,这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载。
当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。

6、直接内存

运行时常量池,无法申请内存时会抛出OutOfMemoryError异常,不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域。
假如说对虚拟机进行内存分配,忽略了直接内存,使各个内存区域总和大于物理内存限制,从而导致动态扩展时出现OutOfMemoryError异常。

你可能感兴趣的:(面试)