文章目录
Java堆溢出
一直循环new对象
分析:
先判断是内存泄漏还是内存溢出。先通过工具分析出oom的对象存在是否是有必要的,没有则是内存泄漏,有则是内存溢出。
内存泄漏,先从gcroot根节点不行向下找到目标对象。
内存溢出则,看是否有办法扩展堆的空间(通过减少方法区,栈的空间),检查对象是否有生命期过长消耗内存过多设计不合理的情况。
虚拟机栈和本地方法栈溢出
减小栈深度(xss设置),在方法内无限递归调用,Stack Overflow。
减小栈深度(xss设置),在方法内设置大量的变量,然后无限递归调用,和第一个相比栈深度小了,Stack Overflow。
用栈内存可以动态扩展的虚拟机执行上述方式会报outofmemerry异常。
不停地新建新线程,每个线程里都有一个方法,会报outofmemerry异常,除了堆和方法区外每个线程都会占用一段系统内存,当系统内存不够时,无法为栈分配新内存就会报异常。
方法区和运行时常量池溢出
常量池:
不停地造不同的字符串,使用intern方法,在jdk7之前会永久代溢出异常,jdk7之后会堆溢出异常。
实验:
Jdk7之前,builder在堆区创建字符串,intern指向的是常量池(在方法区)所以不一样,jdk7之后常量池移入了堆中,intern和builder指向的相同。
方法区:
不停地造类(不是new实例),在jdk8之前会报永久代溢出异常,在jdk8之后会报元空间溢出异常。
本地内存直接内存溢出
由native为直接内存分配空间后,由unsafe类支配其中的空间(无限循环支配可报溢出异常),不用DirectByteBuffer支配,因为unsafe类是直接支配,DirectByteBuffer是间接支配。