文章收录在网站:http://hardyfish.top/
文章收录在网站:http://hardyfish.top/
文章收录在网站:http://hardyfish.top/
文章收录在网站:http://hardyfish.top/
内存溢出异常
Java堆溢出
Java堆内存的OutOfMemoryError异常是实际应用最常见的内存溢出情况
- 异常堆栈信息
java.lang.OutOfMemoryError
会进一步提示Java heap space
解决方法:
- 首先通过内存映像分析工具(如
Eclipse Memory Analyzer
)对Dump出来的堆转储快照进行分析- 分析清楚是出现内存泄漏(Memory Leak)还是内存溢出(Memory overflow),即导致OOM的对象是否是必要的
- 如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots的引用链
- 找到泄漏对象是通过怎样的引用路径、与哪些GC Roots相关联,才导致垃圾收集器无法回收它们
- 根据泄漏对象的类型信息以及它到GC Roots 引用链的信息,一般可以比较准确地定位到这些对象创建的位置
- 进而找到产生内存泄漏的代码具体位置
- 如果是内存溢出,检查Java虚拟机的堆参数(-Xmx与-Xms)设置
- 检查代码对象生命周期是否过长、存储结构设计不合理等情况,减少程序运行的内存消耗
虚拟机栈和本地方法栈溢出
线程请求的栈深度大于虚拟机所允许的最大深度,将抛出
StackOverflowError
异常如果虚拟机栈允许动态扩展,当扩展栈容量无法申请到足够的内存,将抛出OutOfMemoryError异常
方法区和运行时常量池溢出
运行时常量池溢出时,在
OutOfMemoryError
异常后面跟随的提示信息是PermGen space类加载过多,会导致方法区内存溢出,在实际的应用中,如Spring框架,会使用到CGLib这类字节码技术,会产生大量的动态类
- 容易导致内存溢出,需要注意垃圾回收;除此之外常见的还有大量JSP或动态JSP文件应用、基于OSGi的应用等
在JDK8后,永久代完全退出,元空间作为替代者登场
在默认设置下,动态创建新类型已经很难使虚拟机出现产生方法区内存溢出
本机直接内存溢出
--XX:MaxDirectMemorySize
设置,如不指定,默认与Java堆最大值(-Xmx指定)一致出现的明显特征,Heap Dump文件不会看见明显的异常情况,如发现内存溢出后产生的Dump文件很小
- 而程序又直接或间接使用了
DirectMemory
(典型的间接使用是NIO),那可以考虑重点检查直接内存的问题