一、得分点
增加内存、错误日志、代码走查、内存查看工具
二、标准回答
内存溢出,简单地说内存溢出就是指程序运行过程中申请的内存大于系统能够提供的内存,导致无法申请到足够的内存,于是就发生了内存溢出。
引起内存溢出的原因有很多种,常见的有以下几种:
1. 内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
2. 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
3. 代码中存在死循环或循环产生过多重复的对象实体;
4. 使用的第三方软件中的BUG;
5. 启动参数内存值设定的过小。
内存溢出的解决方案:
– 第一步,修改JVM启动参数,直接增加内存。
– 第二步,检查错误日志,查看“OutOfMemory”错误前是否有其它异常或错误。
– 第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。
– 第四步,使用内存查看工具动态查看内存使用情况。
三、加分回答
除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OOM异常的可能。
1. Java堆溢出
Java堆用于储存对象实例,我们只要不断地创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么随着对象数量的增加,总容量触及最大堆的容量限制后就会产生内存溢出异常。
2. 虚拟机栈和本地方法栈溢出
HotSpot虚拟机中并不区分虚拟机栈和本地方法栈,如果虚拟机的栈内存允许动态扩展,当扩展栈容量无法申请到足够的内存时,将抛出OutOfMemoryError异常。
3. 方法区和运行时常量池溢出
方法区溢出也是一种常见的内存溢出异常,在经常运行时生成大量动态类的应用场景里,就应该特别关注这些类的回收状况。这类场景常见的包括:
程序使用了CGLib字节码增强和动态语言、大量JSP或动态产生JSP文件的应用、基于OSGi的应用等。
在JDK 6或更早之前的HotSpot虚拟机中,常量池都是分配在永久代中,即常量池是方法区的一部分,所以上述问题在常量池中也同样会出现。
而HotSpot从JDK 7开始逐步“去永久代”的计划,并在JDK 8中完全使用元空间来代替永久代,所以上述问题在JDK 8中会得到避免。
4. 本地直接内存溢出
直接内存的容量大小可通过`-XX:MaxDirectMemorySize`参数来指定,如果不去指定,则默认与Java堆最大值一致。如果直接通过反射获取Unsafe实例进行内存分配,并超出了上述的限制时,将会引发OOM异常。
转载请注明:XAMPP中文组官网 » 大厂面试题:请你说说内存溢出