一、Java内存泄露例子

Vector v = new Vector( 10 );

for ( int i = 1 ;i < 100 ; i ++ ){

Object obj = new Object();

v.add(obj);

obj = null ;

}

在这个例子中,代码栈中存在Vector 对象的引用 v 和 Object 对象的引用 obj 。在 For 循环中,我们不断的生成新的对象,然后将其添加到 Vector 对象中,之后将 obj  引用置空。问题是当 obj  引用被置空后,如果发生 GC ,我们创建的 Object 对象是否能够被 GC 回收呢?答案是否定的。因为, GC 在跟踪代码栈中的引用时,会发现 v 引用,而继续往下跟踪,就会发现 v 引用指向的内存空间中又存在指向 Object 对象的引用。也就是说尽管 obj  引用已经被置空,但是 Object 对象仍然存在其他的引用,是可以被访问到的,所以 GC 无法将其释放掉。如果在此循环之后, Object 对象对程序已经没有任何作用,那么我们就认为此 Java 程序发生了内存泄漏。

在不涉及复杂数据结构的一般情况下,Java 的内存泄露表现为一个内存对象的生命周期超出了程序需要它的时间长度。我们有时也将其称为“对象游离”。

public class FileSearch{

private byte [] content;

private File mFile;

public FileSearch(File file){

mFile = file;

}

public boolean hasString(String str){

int size = getFileSize(mFile);

content = new byte [size];

loadFile(mFile, content);

String s = new String(content);

return s.contains(str);

}

}

在这段代码中,FileSearch 类中有一个函数 hasString ,用来判断文档中是否含有指定的字符串。流程是先将mFile 加载到内存中,然后进行判断。但是,这里的问题是,将 content 声明为了实例变量,而不是本地变量。于是,在此函数返回之后,内存中仍然存在整个文件的数据。而很明显,这些数据我们后续是不再需要的,这就造成了内存的无故浪费。

案例1

代码

public static void main(String[] array) throws InterruptedException {

List list = new ArrayList();

int i =0;

while(true)

{

list.add(new MyObj("Str"+i,i++));

}

}

class MyObj

{

public String value;

public int i;

public byte[] b;

public MyObj(String value, int i) {

this.value = value;

this.i = i;

b=new byte[1024*1024];

}

}

命令:

C:\Windows\System32>jps -l

20592

21092 sun.tools.jps.Jps

11024

16268 jconsole.MemoryTest

C:\Windows\System32>jmap -dump:file=16268.bin  16268

Dumping heap to C:\Windows\System32\16268.bin ...

Heap dump file created

将文件16268导入 Memory Analysis Tool

分配了大量的MyObj 对象。结合代码去查找问题,很快就能找到问题。

案例2

MySQL jdbc 5.1.6里,默认情况下,如果一个Connection永远不掉用close,即使你每一个Statement, ResultSet都调用了close,仍然会有内存泄漏,换句话说,Statement的close没有把自己的资源释放干净,Statement会在对应的Connection里有缓存  在我们的项目中采用了数据库链接池的技术,我们的数据库链接应用完成后不是马上调用close方法关闭掉,而是返回给了数据库链接池管理。所以链接池中的活动connettion对象中实际上持有了Statement的引用,造成内存泄露。

通过图中,MAT给出了关于本次检测有两处占用内存较多的疑似泄露,下面是详细说明

先从26%的嫌疑人suspect2看起,报告很直观的给出系统中有13个关于数据库链接的引用对象占用了59.83%的内存资源,我们还可以点击details查看一下详细情况

可以看到这13个数据库链接引用其实就是数据库链接池的数据库链接对象。而数据库链接对象本身仅占用100K左右内存,因此不可能达到26M的内存占用量,所以基本可以断定是数据库链接占用了原查询过程中的一些结果集等对象的引用,造成内存泄露问题。

案例3、

quartz 内存溢出

通过MAT打开dump出来的内存文件,打开后如下图:

从上图可以看到它的大部分功能。1. Histogram可以列出内存中的对象,对象的个数以及大小。2. Dominator Tree可以列出那个线程,以及线程下面的那些对象占用的空间。3.Top consumers通过图形列出最大的object。4.Leak Suspects通过MA自动分析泄漏的原因。

Histogram如下图:

Objects:类的对象的数量。

Shallow size:就是对象本身占用内存的大小,不包含对其他对象的引用,也就是对象头加成员变量(不是成员变量的值)的总和。

Retained size:是该对象自己的shallow size,加上从该对象能直接或间接访问到对象的shallow size之和。换句话说,retained size是该对象被GC之后所能回收到内存的总和。

我们发现ThreadLocal和bingo.persister.dao.Daos类的对象占用了很多空间。

Dominator Tree如下图:

我们发现quartz的定时器的工作线程(10个)占了很多的内存空间

Top consumers如下图:

这里显示了内存中最大的对象有哪些,他们对应的类是哪些,类加载器classloader是哪些。

有些时候,我们在这里就可以看到代码泄露的位置。

Leak Suspects如下图:

从那个饼图,该图深色区域被怀疑有内存泄漏,可以发现整个heap才250M内存,深色区域就占了34%。后面的描述,告诉我们quartz线程占用了大量内存,并指出system class loader加载的"java.lang.ThreadLocal"实例的内存中聚集(消耗空间),并建议用关键字"java.lang.ThreadLocal$ThreadLocalMap$Entry[]"进行检查。所以,MAT通过简单的报告就说明了问题所在。

通过Leak Suspects的Problem Suspect 1点击【Details »】,

如下图如下图所示的上下文菜单中选择 List objects -> with outgoning references, 查看ThreadLocal都应用了些什么对象。

现在看到ThreadLocal中引用的对象如下图:

是dao对象

ps:该dao对象包含一个轻量级的ORM关系内容,所以Retained size比较大。

下面继续查看dao的gc ROOT

如下图所示的上下文菜单中选择 Path To GC Roots -> exclude weak references, 过滤掉弱引用,因为在这里弱引用不是引起问题的关键。

从下图中,可以看到在org.quartz.simpl.SimpleThreadPool中保存了daos的引用。所以可以得出是是因为定时器在运行的过程中持有大量的Daos对象应起了内存泄露。为什么会有那么多的Daos呢,Daos不是一个无状态的单例的、可以重用的吗?继续查看spring配置文件发现Daos的bean配置成scope="prototype",导致定时任务又是每次调用都生产新的Daos实例。由于是Daos是无状态的,修改为单例的,问题解决。

以上是通过MAT分析Tomcat应用程序,找到内存泄露的原因,并解决。

案例4、持久代溢出

public class OOMPermTest {

public static void main(String[] args){

oom();

}

private static void oom(){

Object[] array = new Object[10000000];

for(int i=0; i<10000000; i++){

String d = String.valueOf(i).intern();

array[i]=d;

}

}

intern() 将撑破持久代。

检测java内存泄露_MAT 检测 Java内存泄露检测相关推荐

  1. Java 技术篇-用java自带的内存检测工具排查内存泄漏问题,查看java垃圾回收情况,监控java堆内存变化

    在 java 的 bin 文件夹下有个 jvisualvm.exe 工具,使用它可以检测到 java堆内存 的变化情况,借此可以来检测使用 java 的程序是否存在内存泄漏问题. 我们左边选择程序对应 ...

  2. java线程内存溢出_Java常见问题分析(内存溢出、内存泄露、线程阻塞等)

    Java垃圾回收机制(GC) 1.1 GC机制作用 1.2 堆内存3代分布(年轻代.老年代.持久代) 1.3 GC分类 1.4 GC过程 Java应用内存问题分析 2.1 Java内存划分 2.2 J ...

  3. java 内存泄露 书籍_java虚拟机内存溢出和泄漏实例

    测试参数设置: 1.循环调用new A()实现堆溢出,java.lang.OutOfMemoryError: Java heap space, 虚拟机参数:-Xms1M -Xmx1M -XX:+Hea ...

  4. java 内存泄露 书籍_[Java教程]一次艰难的内存泄露排查,BeanUtils 的锅

    [Java教程]一次艰难的内存泄露排查,BeanUtils 的锅 0 2020-10-29 18:24:42 现象 通过jstat -gcutil pid 5000 ,发现fgc次数很多而且频繁,此时 ...

  5. C/C++内存管理详解以及内存泄露的检测

    文章目录 前言 一.C/C++内存分布? 1.内存布局示意图: 2.内存存放的数据类型 二.C/C++内存管理 1.C内存管理 2.C++内存管理 三.内存泄漏 1.概念 2.Windows平台下检测 ...

  6. Java内存泄漏系列--匿名内部类导致内存泄露--原因/解决方案

    原文网址:Java内存泄漏系列--匿名内部类导致内存泄露--原因/解决方案_IT利刃出鞘的博客-CSDN博客 简介 说明 本文用示例介绍匿名内部类会导致内存泄漏的原因及其解决方案. 相关网址 普通内部 ...

  7. java方法区内存泄露_深入理解java虚拟机-第二章:java内存区域与内存泄露异常...

    2.1概述: java将内存的管理(主要是回收工作),交由jvm管理,确实很省事,但是一点jvm因内存出现问题,排查起来将会很困难,为了能够成为独当一面的大牛呢,自然要了解vm是怎么去使用内存的. 2 ...

  8. 应用jacob组件造成的内存溢出解决方案(java.lang.OutOfMemoryError: Java heap space)

    http://www.educity.cn/wenda/351088.html 使用jacob组件造成的内存溢出解决方案(java.lang.OutOfMemoryError: Java heap s ...

  9. java heap space 什么意思_java内存溢出之Java heap space

    作为一个java程序员,大家都应该认识JVM.JVM作为java的核心,实在太重要了.而内存溢出又是程序员常遇到的错误之一,如果你对JVM的原理足够了解,那么解决这样的问题就不在是一件困难的事情. 关 ...

最新文章

  1. ACM 推荐blog汇总及OJ
  2. 给出一个单链表,不知道节点N的值,只遍历一次就可以求出中间节点,写出算法...
  3. 【PAT乙级】1075 链表元素分类 (25 分)
  4. 【非凡程序员】 OC第十八节课 (数据库mysql和sqlite3)
  5. vim 代码提示功能,让vim可以媲美IDE
  6. iview 输入框_使用iview框架,如何进行输入框或者按钮的关联验证
  7. 今天算做正式开始SP开发吧,第一步当然是将down下来的资料好好地看一看,顺便也记下这些有用的地址...
  8. centos nginx不是命令_Linux使用yum安装nginx服务教程
  9. 异步编程之co——源码分析
  10. HEVC播放器出炉,迅雷看看支持H.265
  11. XShell安装配置教程
  12. 一个IT农民工分享互联网巨头公司面试流程
  13. 南开大学2017年数学分析高等代数考研试题
  14. 博物馆沉浸式体验如何彰显文化价值
  15. 新势力新名片-上海度普新能源通过ASPICE CL2评估!
  16. tableau最大值最小值显示
  17. css3中-moz、-ms、-webkit,-o分别代表的意思,以及微信浏览器内核分析
  18. 学习maven的系列教程(正)
  19. JS对于字符串的切割截取
  20. C++语法特性cheat paper

热门文章

  1. python列表add用法_使用add_edge_list()方法创建图形的最佳方法是什么?
  2. 传递HTML字符串virtual,理解Virtual DOM(1) 真实DOM和虚拟DOM的映射
  3. python编辑七段数码管引脚图_初识原理图
  4. python手写数字识别实验报告_python实现识别手写数字 python图像识别算法
  5. java setmessage_Java Message.setTitle方法代码示例
  6. mysql profiling详解_使用mysql profiling功能剖析单条查询
  7. htm怎么让图片和搜索框在同一行_对于优化来说,内链应该怎么使用你知道吗?...
  8. 创意排版!直通车简约正方形推广设计灵感
  9. 平面设计师常用的网站|素材路上
  10. 中国风春节传统文化海报插画为载体的素材