请描述JVM运行时数据区(程序计数器、堆、栈等)?什么情况下会引发StackOverflowError和OutOfMemoryError?
2条回答 默认 最新
关注JVM运行时数据区
JVM运行时数据区是Java程序执行时操作系统分配的内存区域,主要分为以下几个部分:
程序计数器(PC Register)
- 作用:当前线程所执行的字节码的行号指示器。线程私有。
- 特点:唯一一个在JVM规范中没有规定任何
OutOfMemoryError情况的区域。
Java虚拟机栈(JVM Stack)
- 作用:存储栈帧。每个方法执行时会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。线程私有。
- 异常:
-
StackOverflowError:当线程请求的栈深度大于虚拟机所允许的深度时抛出。 -
OutOfMemoryError:如果虚拟机栈可以动态扩展,而扩展时无法申请到足够内存时抛出。
-
本地方法栈(Native Method Stack)
- 作用:为JVM使用的Native方法服务。线程私有。
- 异常:与Java虚拟机栈一样,会抛出
StackOverflowError和OutOfMemoryError。
Java堆(Java Heap)
- 作用:存放对象实例和数组。是垃圾收集器管理的主要区域(GC堆)。所有线程共享。
- 异常:
-
OutOfMemoryError:当堆中没有内存完成实例分配,并且堆也无法再扩展时抛出。
-
方法区(Method Area)
- 作用:存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。所有线程共享。
- 异常:
-
OutOfMemoryError:当方法区无法满足内存分配需求时抛出。
-
异常触发情况
StackOverflowError
触发情况:最典型的原因是深度递归调用,导致一个线程的虚拟机栈或本地方法栈中压入了过多的栈帧,超出了栈的容量限制。
// 示例:无限递归导致 StackOverflowError public void recursiveMethod() { recursiveMethod(); // 自己调用自己,没有退出条件 }
OutOfMemoryError
- 触发情况:
- Java堆:创建了过多对象,并且有被引用的对象(即垃圾回收器无法回收),导致堆内存耗尽。常见于内存泄漏或处理大量数据时。
// 示例:不断创建对象并保持引用 List<Object> list = new ArrayList<>(); while (true) { list.add(new Object()); // 最终会抛出 OutOfMemoryError: Java heap space } - 方法区(在JDK 8之前是PermGen,之后是Metaspace):动态生成了大量的类(如CGLib、JSP等),或者加载了过多的类。
- 虚拟机栈/本地方法栈:在创建新线程时,无法为线程分配足够的栈内存。这种情况相对少见。
- Java堆:创建了过多对象,并且有被引用的对象(即垃圾回收器无法回收),导致堆内存耗尽。常见于内存泄漏或处理大量数据时。
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报