Java的内存泄漏

如何排查Java内存泄漏? 跟踪可以有不同的格式,因为它们可以由不同的Java内存泄漏检测工具生成,但它们背后的想法总是相同的:在堆中找到不应该存在的对象块,并确定这些对象是否累积而不是释放。在这种情况下,并不是应用程序的错,而是应用程序服务器依赖于默认的堆太小了。正如所讨论的,在许多情况下,Java进程最终会抛出一个OOM运行时异常,这是一个明确的指示,表明您的内存资源已经耗尽。要理解这种跟踪,您应该查看连续的分配失败节,并查找随着时间的推移而减少的释放内存(字节和百分比),同时总内存(此处,19725304)正在增加。... 阅读详情

出自:ibm:developerworks中国网站 欧阳辰周欣
一 问题的提出

Java的一个重要优点就是通过垃圾收集器(Garbage Collection,GC)自动管理内存的回收,程序员不需要通过调用函数来释放内存。因此,很多程序员认为Java不存在内存泄漏问题,或者认为即使有内存泄漏也不是程序的责任,而是GC或JVM的问题。其实,这种想法是不正确的,因为Java也存在内存泄露,但它的表现与C++不同。

随着越来越多的服务器程序采用Java技术,例如JSP,Servlet, EJB等,服务器程序往往长期运行。另外,在很多嵌入式系统中,内存的总量非常有限。内存泄露问题也就变得十分关键,即使每次运行少量泄漏,长期运行之后,系统也是面临崩溃的危险。

二 Java是如何管理内存

为了判断Java中是否有内存泄露,我们首先必须了解Java是如何管理内存的。Java的内存管理就是对象的分配和释放问题。在Java中,程序员需要通过关键字new为每个对象申请内存空间 (基本类型除外),所有的对象都在堆 (Heap)中分配空间。另外,对象的释放是由GC决定和执行的。在Java中,内存的分配是由程序完成的,而内存的释放是有GC完成的,这种收支两条线的方法确实简化了程序员的工作。但同时,它也加重了JVM的工作。这也是Java程序运行速度较慢的原因之一。因为,GC为了能够正确释放对象,GC必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,GC都需要进行监控。

监视对象状态是为了更加准确地、及时地释放对象,而释放对象的根本原则就是该对象不再被引用。

为了更好理解GC的工作原理,我们可以将对象考虑为有向图的顶点,将引用关系考虑为图的有向边,有向边从引用者指向被引对象。另外,每个线程对象可以作为一个图的起始顶点,例如大多程序从main进程开始执行,那么该图就是以main进程顶点开始的一棵根树。在这个有向图中,根顶点可达的对象都是有效对象,GC将不回收这些对象。如果某个对象 (连通子图)与这个根顶点不可达(注意,该图为有向图),那么我们认为这个(这些)对象不再被引用,可以被GC回收。

以下,我们举一个例子说明如何用有向图表示内存管理。对于程序的每一个时刻,我们都有一个有向图表示JVM的内存分配情况。以下右图,就是左边程序运行到第6行的示意图。


Java使用有向图的方式进行内存管理,可以消除引用循环的问题,例如有三个对象,相互引用,只要它们和根进程不可达的,那么GC也是可以回收它们的。这种方式的优点是管理内存的精度很高,但是效率较低。另外一种常用的内存管理技术是使用计数器,例如COM模型采用计数器方式管理构件,它与有向图相比,精度行低(很难处理循环引用的问题),但执行效率很高。

三 什么是Java中的内存泄露

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

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

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

因此,通过以上分析,我们知道在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提供的HotSpot JVM就支持这一特性。

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

Vector v=new Vector(10);
for (int i=1;i<100; i++)
{
Object o=new Object();
v.add(o);
o=null;
}
//此时,所有的Object对象都没有被释放,因为变量v引用这些对象。

四 如何检测内存泄漏

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

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

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

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

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

堆视角。 这是一个全面的视角,我们可以了解堆中的所有的对象信息(数量和种类),并进行统计、排序,过滤。了解相关对象的变化情况。
方法视角。通过方法视角,我们可以得知每一种类的对象,都分配在哪些方法中,以及它们的数量。
对象视角。给定一个对象,通过对象视角,我们可以显示它的所有出引用和入引用对象,我们可以了解这个对象的所有引用关系。
引用图。 给定一个根,通过引用图,我们可以显示从该顶点出发的所有出引用。

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

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

相关资源:

文章:
Jim Patrick, Handling memory leaks in Java programs,
http://www-106.ibm.com/developerWorks/library/j-leaks/index.html
Ed Lycklama, Does Java Technology Have Memory Leaks?
http://www.klgroup.com/javaone
Sun, The Java HotSpot Virtual Machine, Technical White Paper

软件:
Sitraka Software's Jprobe http://www.sitraka.com
Boland Software's Optimizeit http://optimizeit
IBM alphaWorks' Jinsight http://www.alphaworks.ibm.com/tech/jinsight

关于作者
欧阳辰,北京大学计算机硕士毕业,98年起开始研究基于java的软件开发、测试,参与开发、测试过多个基于Java的应用程序和Web服务项目。联系方式yeekee@sina.com
周欣,北京大学计算机系在读博士生,主要研究方向:程序理解、逆向工程及软件度量,联系方式 zhouxin@sei.pku.edu.cn  

Java如何测试内存泄漏 我们知道JVM有自动回收机制,那么我们该怎么去测试程序中发生的内存泄漏呢,那首先是让程序不要运行完,我们可以让其sleep一会儿; 以一个顺序表为例,代码如下: public class Sequence { private Object[] elem; private int usedSize; private static int FA... 阅读详情

相关推荐

Java中典型的内存泄露问题和解决方法

主要介绍了Java中典型的内存泄露问题和解决方法,典型的内存泄露例子是一个没有实现hasCode和equals方法的Key类在HashMap中保存的情况,可以通过实现Key类的equals和hasCode方法解决这种内存泄漏问题,需要的朋友可以参考下

java不存在内存泄露_Java的内存泄露

Java的内存泄露Published:06 May 2014Category:Java有垃圾回收,因此不会出现内存泄露。大错特错。这个说法存在好几个问题。尽管Java的确有垃圾回收器来回收那些不用的内存块,但你不要指望它能够点铁成金。GC减轻了开发人员肩上的负担,而原本的那些工作非常容易出错,不过并不是所有内存分配的问题它都能够解决。更糟糕的是,Java的设计允许它可以欺骗GC,使得它能够保留一些...

weixin_27219587的博客 493

TP4054充电电路发热严重?手把手教你调整电阻值降低温度(附实测数据)

本文针对TP4054锂电池充电电路发热严重的问题,提供了详细的排错与解决方案。通过分析发热原理,指出核心在于PROG引脚电阻值设定,并手把手指导如何计算和选择正确的电阻以降低充电电流与温度。文末附有不同电阻下的实测温度与性能数据,为电子爱好者和工程师提供了实用的调试参考。

p4q5r6s7t的博客 406

java常见的几种内存溢出和解决方案

项目组最近在开发中经常会出现一些意想不到的内存溢出问题。下面我就说说我们常见的几种内存溢出吧!1.JVM Heap(堆)溢出:java.lang.OutOfMemoryError: Java heap spaceJVM在启动的时候会自动设置JVM Heap的值, 可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置。Heap的大小是Young...

weixin_33894640的博客 808

XR Interaction Toolkit实战:为HTC Vive Cosmos打造抓取、投掷与UI交互(Unity 2023教程)

本文详细介绍了如何使用Unity 2023和XR Interaction Toolkit为HTC Vive Cosmos开发抓取、投掷与UI交互系统。通过实战案例'VR投掷训练室',从基础配置到高级功能实现,涵盖物理抓取、精准投掷机制和VR UI交互设计,帮助开发者提升VR交互开发技能。

weixin_30562507的博客 255

微信小程序-如何根据缩放屏幕大小自适应icon图标更改marker

微信小程序如何根据用户的缩放屏幕来改变marker图标icon的大小,实现icon自适应屏幕缩放的效果

Bartender_VA11的博客 3980

Java内存泄漏概念、造成原因及检测方式(全)

本身java有垃圾回收器GC,可以内存管理,但为什么还会造成内存泄漏(内存泄漏不等于内存溢出),内存泄漏在项目实战或者企业项目是不被允许,甚至在企业面试中也是常考的题型。

码农研究僧的博客 6326

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】5.2 数据分组与透视(CUBE/ROLLUP/GROUPING SETS)

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】5.2 数据分组与透视(CUBE/ROLLUP/GROUPING SETS)

kngines 1835

java基础回顾第四章:面向对象(上)

类与对象,封装,方法,重载

weixin_43530798的博客 266

多agv系统调度的MATLAB仿真

从起点出发,到货物点领取货物最后到卸货点,以完成任务总时间最短为目标进行单目标优化,约束条件为,任务不冲突,路径不冲突,要能实现路径规避 ,4-6台agv一起工作。左右货架间隔可通过1个agv,上下货架间隔可通过两个agv,通道为双向行驶通道。一台agv只能带一个货物,优化目标为完成任务总的时间最短,agv的速度是匀速,转弯也不会减速,取货物时间为固定值。上面的图里面货物看为正方形跟agv一样的长度大小,agv试做是跟货物一样大小的正方形agv的速度是每秒1个车身。多台agv一起完成...

FPGA/MATLAB学习教程/源码/项目合作开发 7564

会员管理小程序实战开发04-用户登录及注册

上一节我们介绍了用户信息数据源的创建及网格布局的使用,本节的话我们讲解用户的登录及注册功能任何开发。 在我们前述章节里介绍的,不论是管理员表还是用户表,都涉及到一个问题就是openid,那这个openid如何获取呢?如果我直接把代码贴给你,就缺失了一个思考的过程。既然这个是微信提出的概念,那么必然就会有官方文档作为对应。程序开发的基本功就是要会看官方文档,很多初学的开发同学可能会对官方文档颇有诟病,觉得不够基础。怎么说呢,当你进入到开发岗之后,自学能力是必要的,还是要试着可以看懂官方文档才好。 登录接口解读

低代码布道师的博客 1567

在java开发项目中内存泄漏的五大原因,遇到内存泄漏我们该怎么做,怎么避免内存泄漏

​内存泄漏(Memory Leak)是指程序在申请内存后,无法释放已不再使用的内存的情况。通俗来说,就是程序中某些对象已经不再被使用,但由于某些原因仍然被其他对象引用,导致垃圾回收器(Garbage Collector)无法将它们从内存中回收,最终造成内存资源浪费的现象。内存泄漏的本质是对象的生命周期管理不当。在 Java 等具备自动垃圾回收机制的语言中,对象的创建和销毁由系统自动管理,但如果代码中存在不合理的引用关系,会导致对象无法被及时回收,从而占用内存空间。

Chenchen0905_的博客 3260

基于R-CNN深度学习的石头剪刀布手势识别系统:数据集、模型和UI界面的完整实现

本项目的目标是开发一个基于R-CNN深度学习模型的手势识别系统,能够识别石头、剪刀、布三种手势,并通过UI界面让用户能够进行交互。数据集准备与标注:收集包含石头剪刀布手势的图像,并对其进行标注。深度学习模型构建与训练:采用R-CNN模型进行手势的识别和定位。UI界面设计:设计一个简洁的界面,用户可以上传手势图像并进行识别。R-CNN(Region Convolutional Neural Networks)是一个典型的目标检测模型。生成候选区域。

YOLO 876

如何排查Java内存泄漏

没有经验的程序员经常认为Java的自动垃圾回收完全使他们免于担心内存管理。这是一个常见的误解:虽然垃圾收集器做得很好,但即使是最好的程序员也完全有可能成为严重破坏内存泄漏的牺牲品。让我解释一下。 当不必要地维护不再需要的对象引用时,会发生内存泄漏。这些泄漏很糟糕。首先,当程序消耗越来越多的资源时,它们会对计算机施加不必要的压力。更糟糕的是,检测这些泄漏可能很困难:静态分析通常很难精确识别这些冗余引用,现有的泄漏检测工具会跟踪和报告有关单个对象的细粒度信息,产生难以解释且缺乏精确度的结果。 换句话说,泄漏要么

sutianxiao的博客 2373

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

java 内存泄漏_如何排查Java内存泄漏?看完你就明白了

没有经验的程序员经常认为Java的自动垃圾回收完全使他们免于担心内存管理。这是一个常见的误解:虽然垃圾收集器做得很好,但即使是最好的程序员也完全有可能成为严重破坏内存泄漏的牺牲品。让我解释一下。当不必要地维护不再需要的对象引用时,会发生内存泄漏。这些泄漏很糟糕。首先,当程序消耗越来越多的资源时,它们会对计算机施加不必要的压力。更糟糕的是,检测这些泄漏可能很困难:静态分析通常很难精确识别这些冗余引用...

weixin_39601642的博客 402

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

如何在 Java 中进行内存泄漏分析

确认是否发生内存泄漏:通过jstat观察 GC 状态,确认是否存在问题。生成和分析 Heap Dump:使用jmap获取 Heap Dump 文件,并利用 MAT 或 VisualVM 工具分析。定位问题和修复代码:找到内存泄漏的根源后,通过优化对象管理和生命周期修复问题。

Mylqs的博客 2471

Java内存泄漏分析和解决

内存泄漏:对象已经没有被应用程序使用,但是垃圾回收器没办法移除它们,因为还在被引用着。在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是可达的,即在有向图中,存在通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对象。如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存。在C++中,内存泄漏的范围更大一些。

RayPick的博客 1万+

Java内存泄漏

Java 的核心优势之一是在内置垃圾收集器(或简称GC )的帮助下进行自动内存管理。GC 隐式地负责分配和释放内存,因此能够处理大多数内存泄漏问题。虽然 GC 有效地处理了大部分内存,但它并不能保证万无一失的内存泄漏解决方案。GC 非常聪明,但并非完美无缺。内存泄漏仍然可能悄悄发生,即使是在认真的开发人员的应用程序中也是如此。仍然可能存在应用程序生成大量多余对象的情况,从而耗尽关键内存资源,有时会导致整个应用程序失败。内存泄漏是 Java 中的一个真正问题。

weixin_43541852的博客 1376

JAVA内存泄漏

JAVA内存泄漏 1.介绍 Java的一个重要特性是通过垃圾收集器(GC)自动管理内存的回收,而不需要程序员自己释放内存,理论上Java中所有不会再被使用的对象所占用的内存都可以被GC回收,但是Java还是存在内存泄漏。 2.内存分配 在Java程序中,我们通常使用new为对象分配内存,这些内存空间都在堆(Heap)上。例如: public class Demo1 { public static void main(String[] args) { Object object1 =

zh123456_789的博客 333

java内存泄漏分析

  java.lang.OutOfMemoryError是工作中常见的异常,今天介绍下如何分析java内存泄漏。   java内存分析工具很多,JDK安装目录下自带就有很多优秀的分析工具。分析堆栈时我比较推荐使用MAT,方便,快速。 安装MAT 打开eclipse ---&gt;help---&gt;eclipse marketplace(我在公司一般会下载高版本的eclipse,它带有一个插...

wflh323的专栏 7154

java中是否存在内存泄漏?什么情况下才是内存泄漏?

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

qq_44941119的博客 943

Java和内存泄漏

总览 术语“内存泄漏”在Java中的使用方式不同于在其他语言中使用的方式。 通用术语中的“内存泄漏”是什么意思,在Java中如何使用? 维基百科的定义 当计算机程序消耗内存但无法将其释放回操作系统时,就会发生计算机科学中的内存泄漏(在此情况下为泄漏)。 JVM在启动时将堆保留为虚拟内存,并且直到退出后才将其归还。 该虚拟内存在使用时会变成主内存。 这就是为什么JVM的虚拟大小和驻...

最佳 Java 编程 216

java string 内存泄漏_Java内存泄漏

Java内存泄漏解释内存泄漏: 存在一些被分配的对象,满足两个特点:对象是可达的:在有向图中,存在通路与之相连.对象是无用的:程序以后不再使用这些对象.结果:消耗越来越多的内存资源,最终导致OutOfMemoryError。与C++的区别:C++:对象被分配内存空间,却不可达.Java:不可达的对象由GC回收.示例:Vector v = new Vector(10);for(int i = 0; ...

weixin_36222664的博客 328
上一篇: Java各类IDE一点使用心得
下一篇: 如何修改MySQL root密码
Ostroff
博客等级 码龄18年 59粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值