主题
面试速答(先看这里)
**一句话结论:**OutOfMemory一般发生在Java的堆内存上,StackOverflow一般发生在Java的栈内存中。
60秒标准回答:
OutOfMemory 是内存溢出错误,他通常发生在程序试图分配内存时,但是超出可用内存限制。这可能是因为程序使用了太多内存,或者由于内存泄漏而导致内存不断累积
StackOverflow 是栈溢出错误,他通常发生在程序的调用栈变得过深时,如递归调用。每次函数调用都会在栈上分配一些内存,当递归调用或者函数调用层次过深时,栈空间会被耗尽,从而导致StackOverflowError
OutOfMemory一般发生在Java的堆内存上,StackOverflow一般发生在Java的栈内存中。但是也不绝对,在栈上也可能发生OutOfMemory
**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点
回答主线:
- **要点1:**OutOfMemory 是内存溢出错误,他通常发生在程序试图分配内存时,但是超出可用内存限制。
- **要点2:**StackOverflow 是栈溢出错误,他通常发生在程序的调用栈变得过深时,如递归调用。
- **要点3:**在《Java虚拟机规范》规定了: 如果虚拟机的栈内存允许动态扩展,当扩展栈容量无法申请到足够的内存时,将抛出OutOfMemoryError异常。
- **要点4:**在某些编程语言和运行时环境中,栈内存允许动态扩展,而不会固定在一个特定的大小。
- **要点5:**所以,在HotSpot虚拟机中是不会出现因为栈空间不足而抛出OutOfMemoryError异常的情况的,只会发生StackOverflow。
**记忆锚点:**Java → OutOfMemory → StackOverflow → OutOfMemoryError → native → Space
关键取舍:
- OutOfMemory 是内存溢出错误,他通常发生在程序试图分配内存时,但是超出可用内存限制。
- Requested array size exceeds VM limit :这个错误发生在试图创建一个太大的数组,超过了虚拟机的限制。
- Unable to create new native thread:这个错误发生在虚拟机无法创建更多的本机线程,通常由于操作系统限制引起。
易错提醒:
- 它发生在Java堆内存不足,通常由程序中创建的对象过多或者单个对象太大引起。
- PermGen Space(在Java 7之前)或 Metaspace(在Java 8及更高版本):这种错误发生在永久代(Java 7之前)或元空间(Java 8及更高版本)不足。
加分表达:
- 在《Java虚拟机规范》规定了: 如果虚拟机的栈内存允许动态扩展,当扩展栈容量无法申请到足够的内存时,将抛出OutOfMemoryError异常。
追问准备:
- 围绕「Java」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「OutOfMemory」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「StackOverflow」:底层原理是什么?使用时有哪些边界和常见坑?
- 如果线上出现异常,你会如何定位、验证并规避?
典型回答
OutOfMemory 是内存溢出错误,他通常发生在程序试图分配内存时,但是超出可用内存限制。这可能是因为程序使用了太多内存,或者由于内存泄漏而导致内存不断累积。
StackOverflow 是栈溢出错误,他通常发生在程序的调用栈变得过深时,如递归调用。每次函数调用都会在栈上分配一些内存,当递归调用或者函数调用层次过深时,栈空间会被耗尽,从而导致StackOverflowError。
OutOfMemory一般发生在Java的堆内存上,StackOverflow一般发生在Java的栈内存中。但是也不绝对,在栈上也可能发生OutOfMemory。
扩展知识
OutOfMemory
OutOfMemory在具体报错上还有以下几种情况:
- Java Heap Space:这是最常见的OutOfMemoryError。它发生在Java堆内存不足,通常由程序中创建的对象过多或者单个对象太大引起。这种错误可能导致Java应用程序崩溃。
- PermGen Space(在Java 7之前)或 Metaspace(在Java 8及更高版本):这种错误发生在永久代(Java 7之前)或元空间(Java 8及更高版本)不足。通常由于加载过多的类或创建过多的动态代理类等原因引起。
- Native Heap:这种错误发生在本机堆内存不足。Java虚拟机使用本机代码(native code)来执行某些操作,如本机方法,这些操作可能会占用本机堆内存。
- Direct Memory:这种错误发生在程序使用NIO(New I/O)库或直接内存缓冲区时,由于分配了过多的直接内存而耗尽。
- GC Overhead Limit Exceeded:这个错误发生在垃圾收集器花费了太多时间进行垃圾回收,而没有足够的内存被释放。这通常是由于内存不足以满足垃圾收集需求而引起的。
- Requested array size exceeds VM limit:这个错误发生在试图创建一个太大的数组,超过了虚拟机的限制。
- Unable to create new native thread:这个错误发生在虚拟机无法创建更多的本机线程,通常由于操作系统限制引起。
栈上OOM
在《Java虚拟机规范》规定了:如果虚拟机的栈内存允许动态扩展,当扩展栈容量无法申请到足够的内存时,将抛出OutOfMemoryError异常。
在某些编程语言和运行时环境中,栈内存允许动态扩展,而不会固定在一个特定的大小。这种情况下,栈内存可以动态增加,以适应程序的需要。然而,这种实现在Java中并不常见,如我们常用的Hotspot虚拟机种,栈内存是有限且固定的,不能动态扩展。
所以,在HotSpot虚拟机中是不会出现因为栈空间不足而抛出OutOfMemoryError异常的情况的,只会发生StackOverflow。