JVM相关--内存溢出分析及解决方案

声明:下文所有经验总结均参考书籍《深入理解JAVA虚拟机》,如有侵权,请联系本人删除。

1,堆内存溢出:异常信息会提示java.lang.OutOfMemoryError,随后会紧跟heap space信息。
可能是堆里面的对象太多,堆无法放下那么多对象实例。
也可能是有资源没有来得及及时回收,比如某些大型对象没有调用close()方法。
解决这种内存溢出的方法:
1)如果可以调大jvm内存,通过调整-Xmx=1024M -Xms=512M的参数调大虚拟机内存,看看内存是否还会溢出;
2)如果上述方法不行,则需要进一步分析内存溢出的原因,可能需要通过内存映像分析工具,分析dump出来的堆转储快照,分析到底是内存溢出还是内存泄露。内存泄露是指无用对象无法被回收,比如某个对象没有调用close方法。或者某个对象一直保持着引用,没有及时释放。内存溢出就是单纯地堆空间不够存放有用的对象。
如果是内存溢出,则使用方法1);如果是内存泄露,则需要使用分析堆转储快照分析出泄露对象到gc roots的引用链找出相应的对象。

2,方法栈溢出:异常信息会提示java.lang.StackOverFlowError.
一般是方法递归的深度太大导致。
这个解决就比较简单,找出方法并修改至合理即可。
单线程一般都只会抛出java.lang.StackOverFlowError,如果是多线程情况下,线程多了栈的请求深度仍然那么大,就可能导致java.lang.OutOfMemoryError,这种时候可以调小堆的大小,和栈的容量(深度)来解决。

3,方法区溢出:因为方法区本身就是堆的一部分,所以提示信息和堆溢出一样。
如果是这个区域产生了溢出,可能是由于加载的类信息太多,要判断哪些类是无用的比较困难,一般只能通过方法区的容量来解决。使用参数:
-XX:PermSize=20M -XX:MaxPermSize=30M来调整,如果是常量池溢出,也只能通过调整方法区来间接调整常量池大小。

4,本机直接内存溢出:异常信息提示java.lang.OutOfMemoryError
这种异常产生之后堆转储快照里面不会有明显的异常,如果代码中使用了nio,就可能会产生这种异常,一般从这个思路去解决。

Guess you like

Origin blog.csdn.net/qq_36779082/article/details/88829060