Java如何检测内在泄漏呢?我们需要一些工具进行检测,并发现内存泄漏问题。
编写java程序最为方便的地方就是我们不需要管理内存的分配和释放,一切由jvm来进行处理,当java对象不再被应用时,等到堆内存不够用时,jvm会进行垃圾回收,清除这些对象占用的堆内存空间,如果对象一直被应用,jvm无法对其进行回收,创建新的对象时,无法从Heap中获取足够的内存分配给对象,这时候就会导致内存溢出。
而出现内存泄露的地方,一般是不断的往容器中存放对象,而容器没有相应的大小限制或清除机制。容易导致内存溢出。当服务器应用占用了过多内存的时候,如何快速定位问题呢?
我们先来了解几个知识点:
设置每个线程栈大小:-Xss10M
改变栈的大小:
1、可以调整线程的调用层次
2、可以控制虚拟机运行的线程数
常见错误:java.lang.StackOverflowError:栈空间不足
垃圾回收算法:
分代处理
年轻代
伊甸区--eden
幸存区
年老代
改变堆大小:
-Xms--初始堆内存大小
-Xmx--最大堆内存大小
设置规则:-Xms=-Xmx
内存泄漏定位:--
OutofMemoryError产生的原因:
1、内存泄漏
2、堆内存不足
判定内存泄漏的方法:
1、在压力稳定的情况下监控堆内存的变化。
2、监控堆内存使用情况,如果发现堆内存有不断增加的趋势,初步可以判断内存泄漏。
3、在压力稳定过程中(时间较长),对堆内存做dump。
生成堆的dump文件:通过JMX的MBean生成当前的Heap信息,大小为一个3G(整个堆的大小)的hprof文件,如果没有启动JMX可以通过Java的jmap命令来生成该文件。
4、借助于MAT分析dump文件,观察对象使用情况
EclipseMAT是SAP公司贡献的一个工具,可以在Eclipse网站下载到它,完全免费的。 要定位问题,首先你需要获取服务器jvm某刻内存快照。jdk自带的jmap可以获取内存某一时刻的快照,导出为dmp文件后,就可以用Eclipse MAT来分析了,找出是那个对象使用内存过多。
堆内存分析:
1、哪些对象一直在增加?借助于工具的增量功能
2、找到重点对象(增加速度和大小都比较大的)
3、分析对象之间的关系--out in
4、分析这些对象是哪些线程产生的?分析dump的线程数据
5、分析线程栈,定位代码
堆dump,一定在服务器端完成,不要借助于网络工具:jmap
通过Mat我们能清楚地看到,哪些对象被怀疑为内存泄漏,哪些对象占的空间最大及对象的调用关系。另,通过Mat或JMX我们还可以分析线程状态,可以观察到线程被阻塞在哪个对象上,从而判断系统的瓶颈。
正常的堆空间垃圾回收图示JVM和Visual GC:
程序出现异常的堆空间垃圾回收图示JVM和Visual GC: