- 1、本文档共10页,可阅读全部内容。
- 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
一次内存泄露问题的排查系统对外提供的Solr查询接口,在来自外部调用的压力加大之后,就会出现solr查询报Read Timed Out的异常,从表面现象上看是此时solr核压力过大,无法响应过多的查询请求。??????但实际上此时并发查询压力并不是很大,那么为何solr核会无法及时响应查询请求呢?首先用top查看了下load average,也是很低,也佐证了系统本身压力并不大。??????然后,用jstack –l pid?查看那些cpu使用率过高的线程,发现全都是GC线程,说明GC过于频繁,而且耗时过长,导致应用线程被挂起,无法响应客户端发来的请求,这种情况就应该是有存在内存泄露的问题咯。??于是,就用jmap将进程的堆转储文件dump出来到heap.bin文件中JMap -dump:format=b,file=/tmp/heap.bin pid然后用Eclipse Memory Analyzer(MAT)打开堆转储文件进行分析通常我们都会采用下面的“三步曲”来分析内存泄露问题:首先,对问题发生时刻的系统内存状态获取一个整体印象。第二步,找到最有可能导致内存泄露的元凶,通常也就是消耗内存最多的对象?? ?接下来,进一步去查看这个内存消耗大户的具体情况,看看是否有什么异常的行为。下面将用一个基本的例子来展示如何采用“三步曲”来查看生产的分析报告。??如上图所示,在报告上最醒目的就是一张简洁明了的饼图,从图上我们可以清晰地看到一个可疑对象消耗了系统75%?的内存。现在,让我们开始真正的寻找内存泄露之旅,点击“Leak ?Suspects”链接,可以看到如下图所示对可疑对象的详细分析报告。我们查看下从?GC?根元素到内存消耗聚集点的最短路径??我们可以很清楚的看到整个引用链,内存聚集点是一个拥有大量对象的列表,如果你对代码比较熟悉的话,相信这些信息应该能给你提供一些找到内存泄露的思路了。接下来,我们再继续看看,这个对象集合里到底存放了什么,为什么会消耗掉如此多的内存。?在这张图上,我们可以清楚的看到,这个列表中保存了大量?HashMap?对象的引用,就是它导致的内存泄露。至此,我们已经拥有了足够的信息去寻找泄露点,回到代码中就发现,List没有clear或者设置为null,导致其包含的强引用的各个HashMap没有得到释放。至此,问题得到解决。下面我们来继续深入研究java的内存泄露问题。Java的一个重要优点就是通过垃圾收集器(Garbage Collection,GC)自动管理内存的回收,程序员不需要通过调用函数来释放内存。因此,很多程序员认为Java不存在内存泄漏问题,或者认为即使有内存泄漏也不是程序的责任,而是GC或JVM的问题。其实,这种想法是不正确的,因为Java也存在内存泄露,但它的表现与C++不同。随着越来越多的服务器程序采用Java技术,例如JSP,Servlet,?EJB等,服务器程序往往长期运行。另外,在很多嵌入式系统中,内存的总量非常有限。内存泄露问题也就变得十分关键,即使每次运行少量泄漏,长期运行之后,系统也是面临崩溃的危险。为了判断Java中是否有内存泄露,我们首先必须了解Java是如何管理内存的。Java的内存管理就是对象的分配和释放问题。在Java中,程序员需要通过关键字new为每个对象申请内存空间?(基本类型除外),所有的对象都在堆?(Heap)中分配空间。另外,对象的释放是由GC决定和执行的。在Java中,内存的分配是由程序完成的,而内存的释放是有GC完成的,这种收支两条线的方法确实简化了程序员的工作。但同时,它也加重了JVM的工作。这也是Java程序运行速度较慢的原因之一。因为,GC为了能够正确释放对象,GC必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,GC都需要进行监控。监视对象状态是为了更加准确地、及时地释放对象,而释放对象的根本原则就是该对象不再被引用。为了更好理解GC的工作原理,我们可以将对象考虑为有向图的顶点,将引用关系考虑为图的有向边,有向边从引用者指向被引对象。另外,每个线程对象可以作为一个图的起始顶点,例如大多程序从main进程开始执行,那么该图就是以main进程顶点开始的一棵根树。在这个有向图中,根顶点可达的对象都是有效对象,GC将不回收这些对象。如果某个对象?(连通子图)与这个根顶点不可达(注意,该图为有向图),那么我们认为这个(这些)对象不再被引用,可以被GC回收。以下,我们举一个例子说明如何用有向图表示内存管理。对于程序的每一个时刻,我们都有一个有向图表示JVM的内存分配情况。以下右图,就是左边程序运行到第6行的示意图。??Java使用有向图的方式进行内存管理,可以消除引用循环的问题,例如有三个对象,相互引用,只要它们和根进程不可达的,那么GC也
文档评论(0)