Java内存泄露检测方法揭秘

开发 后端
在Java中,Java内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是可达的,即在有向图中,存在通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对象。

本文向大家描述一下什么是Java内存泄露及检测方法,首先我们来看一下Java内存泄漏的概念,在Java中,Java内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是可达的,即在有向图中,存在通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对象。

Java内存泄露

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

在C++中,内存泄漏的范围更大一些。有些对象被分配了内存空间,然后却不可达,由于C++中没有GC,这些内存将永远收不回来。在Java中,这些不可达的对象都由GC负责回收,因此程序员不需要考虑这部分的Java内存泄露。

通过分析,我们得知,对于C++,程序员需要自己管理边和顶点,而对于Java程序员只需要管理边就可以了(不需要管理顶点的释放)。通过这种方式,Java提高了编程的效率。

Java内存泄露与C++内存泄露比较

因此,通过以上分析,我们知道在Java中也有内存泄漏,但范围比C++要小一些。因为Java从语言上保证,任何对象都是可达的,所有的不可达对象都由GC管理。

对于程序员来说,GC基本是透明的,不可见的。虽然,我们只有几个函数可以访问GC,例如运行GC的函数System.gc(),但是根据Java语言规范定义,该函数不保证JVM的垃圾收集器一定会执行。因为,不同的JVM实现者可能使用不同的算法管理GC。通常,GC的线程的优先级别较低。JVM调用GC的策略也有很多种,有的是内存使用到达一定程度时,GC才开始工作,也有定时执行的,有的是平缓执行GC,有的是中断式执行GC。

但通常来说,我们不需要关心这些。除非在一些特定的场合,GC的执行影响应用程序的性能,例如对于基于Web的实时系统,如网络游戏等,用户不希望GC突然中断应用程序执行而进行垃圾回收,那么我们需要调整GC的参数,让GC能够通过平缓的方式释放内存,例如将垃圾回收分解为一系列的小步骤执行,Sun提供的HotSpotJVM就支持这一特性。

下面给出了一个简单的Java内存泄露的例子。在这个例子中,我们循环申请Object对象,并将所申请的对象放入一个Vector中,如果我们仅仅释放引用本身,那么Vector仍然引用该对象,所以这个对象对GC来说是不可回收的。因此,如果对象加入到Vector后,还必须从Vector中删除,最简单的方法就是将Vector对象设置为null。

  1. Vectorv=newVector(10);  
  2. for(inti=1;i<100;i++)  
  3. {  
  4.  Objecto=newObject();  
  5.  v.add(o);  
  6.  o=null;   
  7. }  
  8.  
  9. //此时,所有的Object对象都没有被释放,因为变量v引用这些对象。  

#p#如何检测Java内存泄漏

最后一个重要的问题,就是如何检测Java内存泄漏。目前,我们通常使用一些工具来检查Java程序的内存泄漏问题。市场上已有几种专业检查Java内存泄漏的工具,它们的基本工作原理大同小异,都是通过监测Java程序运行时,所有对象的申请、释放等动作,将内存管理的所有信息进行统计、分析、可视化。开发人员将根据这些信息判断程序是否有内存泄漏问题。这些工具包括OptimizeitProfiler,JProbeProfiler,JinSight,Rational公司的Purify等。

下面,我们将简单介绍Optimizeit的基本功能和工作原理。

OptimizeitProfiler版本4.11支持Application,Applet,Servlet和RomoteApplication四类应用,并且可以支持大多数类型的JVM,包括SUNJDK系列,IBM的JDK系列,和Jbuilder的JVM等。并且,该软件是由Java编写,因此它支持多种操作系统。Optimizeit系列还包括ThreadDebugger和CodeCoverage两个工具,分别用于监测运行时的线程状态和代码覆盖面。

当设置好所有的参数了,我们就可以在OptimizeIt环境下运行被测程序,在程序运行过程中,Optimizeit可以监视内存的使用曲线(如下图),包括JVM申请的堆(heap)的大小,和实际使用的内存大小。另外,在运行过程中,我们可以随时暂停程序的运行,甚至强行调用GC,让GC进行内存回收。通过内存使用曲线,我们可以整体了解程序使用内存的情况。这种监测对于长期运行的应用程序非常有必要,也很容易发现Java内存泄露。

检测Java内存泄露

在运行过程中,我们还可以从不同视角观查内存的使用情况,Optimizeit提供了四种方式:

◆堆视角。这是一个全面的视角,我们可以了解堆中的所有的对象信息(数量和种类),并进行统计、排序,过滤。了解相关对象的变化情况。

◆方法视角。通过方法视角,我们可以得知每一种类的对象,都分配在哪些方法中,以及它们的数量。

◆对象视角。给定一个对象,通过对象视角,我们可以显示它的所有出引用和入引用对象,我们可以了解这个对象的所有引用关系。

◆引用图。给定一个根,通过引用图,我们可以显示从该顶点出发的所有出引用。

在运行过程中,我们可以随时观察内存的使用情况,通过这种方式,我们可以很快找到那些长期不被释放,并且不再使用的对象。我们通过检查这些对象的生存周期,确认其是否为Java内存泄露。在实践当中,寻找Java内存泄露是一件非常麻烦的事情,它需要程序员对整个程序的代码比较清楚,并且需要丰富的调试经验,但是这个过程对于很多关键的Java程序都是十分重要的。

总结

综上所述,Java也存在Java内存泄露问题,其原因主要是一些对象虽然不再被使用,但它们仍然被引用。为了解决这些问题,我们可以通过软件工具来检查Java内存泄露,检查的主要原理就是暴露出所有堆中的对象,让程序员寻找那些无用但仍被引用的对象。
 

【编辑推荐】

  1. Java内存泄漏及检测方法
  2. Java内存泄漏的检测和处理
  3. 调用weblogic设置jvmheap大小
  4. 详解Tomcat配置JVM参数步骤
  5. 深入学习JVM内存设置原理和调优

 

 

责任编辑:佚名 来源: ibm.com
相关推荐

2010-09-25 11:23:15

Java内存泄露

2016-09-12 16:01:28

Android内存泄露内存管理

2010-09-25 11:07:45

Java内存泄漏

2017-08-14 16:36:23

ASActivity内存

2010-06-02 13:00:43

Linux 内存监控

2009-12-25 16:10:31

WPF内存

2023-01-26 23:46:15

2018-12-07 10:52:08

内存泄漏方法

2010-08-12 09:30:08

Flex内存泄露

2010-07-29 14:08:05

Flex内存泄露

2013-12-23 09:25:21

2009-06-16 11:11:07

Java内存管理Java内存泄漏

2013-04-09 14:49:18

Linux内存统计内存泄露

2015-05-14 15:38:40

javajava内存泄露

2011-11-17 13:59:41

Java内存管理内存泄露

2015-04-02 16:23:50

C++内存泄露检查

2015-12-07 09:39:27

Java内存泄露

2011-06-16 10:27:55

.NET内存泄漏

2017-12-11 11:00:27

内存泄露判断

2010-05-31 16:53:21

Java
点赞
收藏

51CTO技术栈公众号