Java内存泄漏分析与解决方案(下)

转载 2011年01月11日 17:40:00

 三、几种典型的内存泄漏

  我们知道了在Java中确实会存在内存泄漏,那么就让我们看一看几种典型的泄漏,并找出他们发生的原因和解决方法。

  3.1 全局集合

  在大型应用程序中存在各种各样的全局数据仓库是很普遍的,比如一个JNDI-tree或者一个session table。在这些情况下,必须注意管理储存库的大小。必须有某种机制从储存库中移除不再需要的数据。

  通常有很多不同的解决形式,其中最常用的是一种周期运行的清除作业。这个作业会验证仓库中的数据然后清除一切不需要的数据。

  另一种管理储存库的方法是使用反向链接(referrer)计数。然后集合负责统计集合中每个入口的反向链接的数目。这要求反向链接告诉集合何时会退出入口。当反向链接数目为零时,该元素就可以从集合中移除了。

  3.2 缓存

  缓存一种用来快速查找已经执行过的操作结果的数据结构。因此,如果一个操作执行需要比较多的资源并会多次被使用,通常做法是把常用的输入数据的操作结果进行缓存,以便在下次调用该操作时使用缓存的数据。缓存通常都是以动态方式实现的,如果缓存设置不正确而大量使用缓存的话则会出现内存溢出的后果,因此需要将所使用的内存容量与检索数据的速度加以平衡。

  常用的解决途径是使用java.lang.ref.SoftReference类坚持将对象放入缓存。这个方法可以保证当虚拟机用完内存或者需要更多堆的时候,可以释放这些对象的引用。

  3.3 类装载器

  Java类装载器的使用为内存泄漏提供了许多可乘之机。一般来说类装载器都具有复杂结构,因为类装载器不仅仅是只与"常规"对象引用有关,同时也和对象内部的引用有关。比如数据变量,方法和各种类。这意味着只要存在对数据变量,方法,各种类和对象的类装载器,那么类装载器将驻留在JVM中。既然类装载器可以同很多的类关联,同时也可以和静态数据变量关联,那么相当多的内存就可能发生泄漏。

  四、如何检测和处理内存泄漏

  如何查找引起内存泄漏的原因一般有两个步骤:第一是安排有经验的编程人员对代码进行走查和分析,找出内存泄漏发生的位置;第二是使用专门的内存泄漏测试工具进行测试。

  第一个步骤在代码走查的工作中,可以安排对系统业务和开发语言工具比较熟悉的开发人员对应用的代码进行了交叉走查,尽量找出代码中存在的数据库连接声明和结果集未关闭、代码冗余等故障代码。

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

  4.1检测内存泄漏的存在

  这里我们将简单介绍我们在使用Optimizeit检查的过程。通常在知道发生内存泄漏之后,第一步是要弄清楚泄漏了什么数据和哪个类的对象引起了泄漏。

  一般说来,一个正常的系统在其运行稳定后其内存的占用量是基本稳定的,不应该是无限制的增长的。同样,对任何一个类的对象的使用个数也有一个相对稳定的上限,不应该是持续增长的。根据这样的基本假设,我们持续地观察系统运行时使用的内存的大小和各实例的个数,如果内存的大小持续地增长,则说明系统存在内存泄漏,如果特定类的实例对象个数随时间而增长(就是所谓的“增长率”),则说明这个类的实例可能存在泄漏情况。

  另一方面通常发生内存泄漏的第一个迹象是:在应用程序中出现了OutOfMemoryError。在这种情况下,需要使用一些开销较低的工具来监控和查找内存泄漏。虽然OutOfMemoryError也有可能应用程序确实正在使用这么多的内存;对于这种情况则可以增加JVM可用的堆的数量,或者对应用程序进行某种更改,使它使用较少的内存。

  但是,在许多情况下,OutOfMemoryError都是内存泄漏的信号。一种查明方法是不间断地监控GC的活动,确定内存使用量是否随着时间增加。如果确实如此,就可能发生了内存泄漏。

  4.2处理内存泄漏的方法

  一旦知道确实发生了内存泄漏,就需要更专业的工具来查明为什么会发生泄漏。JVM自己是不会告诉您的。这些专业工具从JVM获得内存系统信息的方法基本上有两种:JVMTI和字节码技术(byte code instrumentation)。Java虚拟机工具接口(Java Virtual Machine Tools Interface,JVMTI)及其前身Java虚拟机监视程序接口(Java Virtual Machine Profiling Interface,JVMPI)是外部工具与JVM通信并从JVM收集信息的标准化接口。字节码技术是指使用探测器处理字节码以获得工具所需的信息的技术。

  Optimizeit是Borland公司的产品,主要用于协助对软件系统进行代码优化和故障诊断,其中的Optimizeit Profiler主要用于内存泄漏的分析。Profiler的堆视图就是用来观察系统运行使用的内存大小和各个类的实例分配的个数的。

  首先,Profiler会进行趋势分析,找出是哪个类的对象在泄漏。系统运行长时间后可以得到四个内存快照。对这四个内存快照进行综合分析,如果每一次快照的内存使用都比上一次有增长,可以认定系统存在内存泄漏,找出在四个快照中实例个数都保持增长的类,这些类可以初步被认定为存在泄漏。通过数据收集和初步分析,可以得出初步结论:系统是否存在内存泄漏和哪些对象存在泄漏(被泄漏)。

  接下来,看看有哪些其他的类与泄漏的类的对象相关联。前面已经谈到Java中的内存泄漏就是无用的对象保持,简单地说就是因为编码的错误导致了一条本来不应该存在的引用链的存在(从而导致了被引用的对象无法释放),因此内存泄漏分析的任务就是找出这条多余的引用链,并找到其形成的原因。查看对象分配到哪里是很有用的。同时只知道它们如何与其他对象相关联(即哪些对象引用了它们)是不够的,关于它们在何处创建的信息也很有用。

  最后,进一步研究单个对象,看看它们是如何互相关联的。借助于Profiler工具,应用程序中的代码可以在分配时进行动态添加,以创建堆栈跟踪。也有可以对系统中所有对象分配进行动态的堆栈跟踪。这些堆栈跟踪可以在工具中进行累积和分析。对每个被泄漏的实例对象,必然存在一条从某个牵引对象出发到达该对象的引用链。处于堆栈空间的牵引对象在被从栈中弹出后就失去其牵引的能力,变为非牵引对象。因此,在长时间的运行后,被泄露的对象基本上都是被作为类的静态变量的牵引对象牵引。

  总而言之, Java虽然有自动回收管理内存的功能,但内存泄漏也是不容忽视,它往往是破坏系统稳定性的重要因素。

分析和解决JAVA 内存泄露的实战例子

这几天,一直在为Java的“内存泄露”问题纠结。Java应用程序占用的内存在不断的、有规律的上涨,最终超过了监控阈值。福尔摩 斯不得不出手了! 分析内存泄露的一般步骤      ...
  • bigtree_3721
  • bigtree_3721
  • 2016年01月20日 18:21
  • 30966

java内存泄漏的定位与分析

1、为什么会发生内存泄漏 java 如何检测内在泄漏呢?我们需要一些工具进行检测,并发现内存泄漏问题,不然很容易发生down机问题。 编写java程序最为方便的地方就是我们不需要管理内存的分配和释...
  • gzh0222
  • gzh0222
  • 2013年01月24日 16:32
  • 47433

Android内存泄漏问题分析及解决方案

总结一下工作中最常见内存泄漏问题,也是自己之前踩过的坑,为了让大家少走弯路,系统全面总结一下内存泄漏问题分析原因及寻找解决方案。...
  • maxwell_nc
  • maxwell_nc
  • 2017年01月26日 09:16
  • 346

java中内存泄露有几种?如何分析泄露原因

一、Java内存回收机制 不论哪种语言的内存分配方式,都需要返回所分配内存的真实地址,也就是返回一个指针到内存块的首地址。Java中对象是采用new或者反射的方法创建的,这些对象的创建都是在堆(He...
  • zhousenshan
  • zhousenshan
  • 2016年10月19日 22:34
  • 2105

使用JDK工具检查运行系统是否存在内存泄露

转自:http://crane-ding.iteye.com/blog/715450     首先在实验之前,先给大家介绍几个jdk自带的工具:  1. jps  查看所有java进程的pid的命令,...
  • spyiu
  • spyiu
  • 2015年09月30日 15:00
  • 1554

jprofiler主要功能简介及内存泄漏分析示例

一、安装JProfiler        从http://www.ej-technologies.com/下载5.1.2并申请试用序列号   二、主要功能简介 1.内存剖析 Memory pr...
  • huangjin0507
  • huangjin0507
  • 2016年09月06日 19:47
  • 3085

内存泄露问题分析方法

本文介绍了内存泄露的定位方法,可以帮助Android系统的开发者定位一些常见的内存泄露问题。本文暂时只从工具的角度讲解了如何定位,后面会补充如何从代码的角度去分析和定位,并且加入内存管理的优化方法。...
  • wlwl0071986
  • wlwl0071986
  • 2015年11月07日 12:24
  • 4344

Java中关于内存泄漏出现的原因以及如何避免内存泄漏(超详细版汇总上)

Android 内存泄漏总结内存管理的目的就是让我们在开发中怎么有效的避免我们的应用出现内存泄漏的问题。内存泄漏大家都不陌生了,简单粗俗的讲,就是该被释放的对象没有释放,一直被某个或某些实例所持有却不...
  • wtt945482445
  • wtt945482445
  • 2016年09月09日 08:58
  • 9100

linux进程之内存泄漏分析

目的:总结linux进程内存泄漏导致crash的分析方法及解决过程 背景:简单使用dlna,但对其源码并无了解 关键节点: 1.问题复现 2.寻找突破口 3.分析日志 4....
  • wuruixn
  • wuruixn
  • 2014年09月03日 22:47
  • 1810

转自美团技术博客的jvm内存泄露分析

Linux与JVM的内存关系分析 引言 在一些物理内存为8g的服务器上,主要运行一个Java服务,系统内存分配如下:Java服务的JVM堆大小设置为6g,一个监控进程占用大约6...
  • veZunShao
  • veZunShao
  • 2014年12月17日 17:21
  • 2442
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java内存泄漏分析与解决方案(下)
举报原因:
原因补充:

(最多只允许输入30个字)