一次内存泄露排查

故事背景

  cpu持续走高,直接导致服务器宕机,无法对外提供服务。

排查思路  

  1. 一般cpu过高只有两种情况:1.线程太多,可以用命令看一下;2.频繁full gc,因为full gc是很消耗cpu资源的。
  2. 用jstat命令看了下,果然是频繁full gc造成的。但是内存分配比例和大小还是很合理的。新生代10g,老年代10g,可是每次ygc后都有1g左右对象去到老年代
  3. 基于上述情况、那这时候调整内存比例也不会有任何意义了,猜想是内存泄露引起的。因为老年代停留了大量对象无法回收,每次稍微ygc过来一点对象就会引起fgc

  于是就生成内存快照进行分析下  jmap -dump:format=b,file=demo.hprof  PID

  

内存泄漏

  1. 下载mat工具 https://www.eclipse.org/mat/downloads.php
  2. 直接打开MemoryAnalyzer.exe就好了。(MemoryAnalyzer.ini文件默认限制了-Xmx1024m,一般生产环境导出的demp很大的,可以把这个调大一点)
  3. file -> open heap dump -> 选择刚才的快照文件就好了

   4. Problem Suspect 1 已经说的很清楚了 java.lang.Thread @ 0xe3805d30 main  线程的java.lang.Object[]占用了53.85%内存对象。

  点击 Details 可以看到 Accumulated Objects in Dominator Tree  的main线程中引用了一个 java.util.ArrayList ,他是一个java.lang.Object[]数组,里面全是demo1对象

  点击 See stacktrace 就能看到线程执行代码堆栈的调用链

  说白了,就是一次性加载过多数据到内存里来导致的,可以考虑数据分批处理或者多个线程并发执行。

什么是内存泄漏及如何避免

     内存泄漏即:对象可达但不可用,程序不需要用某个对象,但另一个正在使用的对象却持有它的引用,导致无法回收停留在堆内中。

     防止内存泄露:

      1.尽早释放无用对象的引用, 将不需要使用的对象设置为null,暗示垃圾收集器来收集该对象,防止发生内存泄漏。  

      2.程序进行字符串处理时,尽量避免使用String,而应该使用StringBuffer。

        3.尽量少用静态变量

      4.尽量运用对象池技术以提高系统性能

posted @ 2021-02-10 13:57  吴磊的  阅读(220)  评论(0编辑  收藏  举报
//生成目录索引列表