Java内存泄漏及性能调优

来源:互联网 发布:淘宝禁售商品奶粉 编辑:程序博客网 时间:2024/05/17 03:00

什么是java中的内存泄露?

在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,
首先,这些对象是可达的,即在有向图中,存在通路可以与其相连;
其次,这些对象是无用的,即程序以后不会再使用这些对象。
如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存。


系统崩溃前的一些现象

    每次垃圾回收的时间越来越长,由之前的10ms延长到50ms左右,FullGC的时间也有之前的0.5s延长到4、5s;FullGC的次数越来越多,最频繁时隔不到1分钟就进行一次FullGC;年老代的内存越来越大并且每次FullGC后年老代没有内存被释放;之后系统会无法响应新的请求,逐渐到达OutOfMemoryError的临界值


如何阻止内存泄漏?

以下是一些阻止内存泄漏的快速动手技巧。
(1)注意集合类,例如HashMap,ArrayList,等等。因为它们是内存泄漏经常发生的地方。当它们被声明为静态时,它们的生命周期就同应用程序的生命周期一般长。
(2)注意事件监听器和回调,如果一个监听器已经注册,但是当这个类不再被使用时却未被注销,就会发生内存泄漏。
(3)“如果一个类管理它自己的内存,程序员应该对内存泄漏保持警惕。”[1] 很多时候当一个对象的成员变量指向其他对象时,不再使用时需要被置为null
(4)一些带close()的连接是否关闭,比如数据库连接(dataSourse.getConnection()),网络连接(socket)和io连接,除非其显式的调用了其close()方法将其连接关闭,否则是不会自动被GC 回收的。
(5)单例模式 持有外部的引用,那么这个对象将不能被JVM正常回收


JAVA内存泄露分析及解决

1、JDK本身提供了一个监视工具jconsole.exe,进入bin文件夹打开后,开始监视JVM内存回收情况,判断老生代的内存发生了泄露
2、虽然知道了存在内存泄露,但是无法判断是哪里发生了泄露,为此我们需要把堆(dump)导出来进行分析,JDK也提供了导出工具jvisualvm.exe,启动后右键点击线程--堆Dump,可以导出Dump文件.(或者使用jmap命令“jmap -dump:format=b,file=heap.hprof pid”进行dump)
3.使用MAT(MemoryAnalyzer)分析Dump文件,该工具的下载地址为:http://www.eclipse.org/mat,可以下载离线版,也可以集成到eclipse,使用很方便.打开该工具导入Dump文件,稍等一会,就可以得出MAT提供的分析报告
4、分析出这个问题点,接下去就是排查代码问题了




很多人都会想到把堆dump下来再用MAT等工具进行分析,但dump堆要花较长的时间,并且文件巨大,再从服务器上拖回本地导入工具,这个过程太折腾不到万不得已最好别这么干。
可以用更轻量级的在线分析,

1、用jmap查看存活的对象情况(jmap -histo:live [pid])


性能调优



线程池:解决用户响应时间长的问题
连接池
JVM启动参数:调整各代的内存比例和垃圾回收算法,提高吞吐量
程序算法:改进程序逻辑算法提高性能