网站首页 > 技术文章 正文
作者 | Java圣斗士,转载请注明出处
全文1800字,阅读大约需要8分钟,建议收藏
小伙伴们大家好,这里是Java圣斗士的IT分享天地。披智慧之荆,斩bug之棘,做一名永不言败的圣斗士。
今天早晨从床上爬起来,翻开了厚厚的《深入理解Java虚拟机》,看到了OutOfMemoryError实战,我想了又想,这东西有什么好实战的?可是我又想了一想,最近倒是有一道面试题考到了和这个OOM 相关的知识,StackOverflowError。
于是乎,便决定将这两个问题好好总结一番,分享给大家,如果大家在面试的过程中遇到这样的问题,至少有一些思路,就是对我最大的安慰了。
一道英文面试题
前两天遇到的面试题是这样的:
If a process reports a stack overflow run-time error, what’s the most possible cause?(2005 摩托罗拉Java面试题)
它说啊,如果一个程序报了stack overflow 运行时错误,那最可能的情况是哪种?题目下方给出了几个选项:
A、lack of memory
B、write on an invalid memory space
C、recursive function calling
D、array index out of boundary
选项A意思是缺少内存,B的意思是写入到了无效的内存空间,C的意思是递归函数的调用,D的意思是数组下标越界。
来来来,大家都认真思考一下这个问题哈。
根据我的经验,stack overflow意思是“栈溢出”而我们在前面的文章中也总结了,Java运行时的逻辑分区总共是五个,口诀是:
两栈一计数,一堆一方法
能够对的上号的就是Java虚拟机栈和本地方法栈了。而本地方法栈不需要我们Java程序员来考虑,所以,这个 stack 就指的是Java虚拟机栈,没跑了!
找到了对应的内存区域,那么我们就来回顾一下JVM栈的功能和作用吧(咦?说好的正确答案呢?小伙伴们别着急……)。
首先,JVM栈是一个“先进后出”的数据结构,它描述的是一个线程在执行过程中方法调用的模型,每个方法在调用之初都会创建一个栈帧,放入到JVM栈中,只要不停地调用,就会不停地向JVM栈中加入栈帧,所以……
咦?分析到这,问题不就清晰了吗?!
方法不停地调用、不停地调用,那慢慢地栈就会被栈帧塞满,导致最后就溢出了呀!所以答案应该是 C——递归函数的调用。
小伙伴们可能又蒙了?函数调用就调用呗,咋还整出来个递归?
其实这个很好理解,递归算法的含义就是函数调用自己本身,不过,造成栈溢出的情况就是递归没有及时返回造成的,我们来看下面这个程序:
public static void main(String[] args) { main(null); }
小伙伴们知道会出现怎样的结果吗?没错!就是StackOverflowError:
那有的小伙伴又要问了,大多数虚拟机栈不是可以自动扩容吗?那如果在自动扩容的时候申请不到更多的内存是不是也同样会报StackOverflowError呢?
的确,大多数栈都可以设置固定大小,同时也可以动态扩容。动态扩容就是在栈空间不够的时候,自动加大栈空间,避免StackOverflow,但是,栈溢出最根本的原因就是线程请求的深度大于虚拟机所允许的深度导致的,因此,就上面的面试题来讲,最可能的情况就是递归的调用,这在StackOverflowError的官方注释中也有描述:
好,解释完了StackOverflowError,我们再来简单说一说OutOfMemoryError(小伙伴们要挺住哦!)
OutOfMemoryError直译过来是——内存耗尽。但是一般人们更习惯称它为“内存泄漏”。
OOM异常可以分为四种情况,这里我需要引述一些《深入理解Java虚拟机》中的知识。
我们最常见的发生OOM的情况就是Java堆溢出。它表示没有更多的内存继续分配给更多的对象了。
但是OOM的情况也需要具体分析,有可能是程序错误,造成了大量的垃圾对象,但却无法被GC回收;也有可能是内存参数太小,导致本身就不能满足程序运行时的需要。
OOM的问题如果要展开讨论,可能我们今天就下不了课了,在这里也只是将日常开发中最常见的几点原因和解决思路分享给大家。
如果希望学习更多的知识,一定要关注我。今天的知识分享就到这里,希望大家喜欢。
---欢迎关注【Java圣斗士】,我是你们的小可爱(?ω?) Morty---
---专注IT职场经验、IT技术分享的灵魂写手---
---每天带你领略IT的魅力---
---期待与您陪伴!---
猜你喜欢
- 2024-10-12 SpringBoot执行jar报错java.lang.OutOfMemoryError_指定内存大小
- 2024-10-12 几种内存溢出(内存溢出类型)
- 2024-10-12 JVM优化:实战OutOfMemoryError异常
- 2024-10-12 JVM 在遇到OOM(OutOfMemoryError)时生成Dump文件的三种方式
- 2024-10-12 线上故障排查全套路,总有一款适合你
- 2024-10-12 面试被问到“零拷贝”!你真的理解吗?
- 2024-10-12 面试夺命三问之《内存溢出和逃逸分析》
- 2024-10-12 阿里面试官:Exception和Error有什么区别?
- 2024-10-12 Eclipse运行大量文件异常OutOfMemoryError: GC overhead limit
- 2024-10-12 记一次线上内存异常排查实战(线上内存泄漏如何定位)
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)