`
darrenzhu
  • 浏览: 806683 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java内存泄露概念与实例

    博客分类:
  • Java
阅读更多
一般来说内存泄漏有两种情况。一种情况如在C/C++语言中的,在堆中的分配的内存,在没有将其释放掉的时候,就将所有能访问这块内存的方式都删掉(如指针重新赋值);另一种情况则是在内存对象明明已经不需要的时候,还仍然保留着这块内存和它的访问方式(引用)。第一种情况,在Java中已经由于垃圾回收机制的引入,得到了很好的解决。所以,Java中的内存泄漏,主要指的是第二种情况。

Vector v=new Vector(10);
for (int i=1;i<100; i++){
	Object o=new Object();
	v.add(o);
	o=null;
}

在这个例子中,代码栈中存在Vector对象的引用v和Object对象的引用o。在For循环中,我们不断的生成新的对象,然后将其添加到Vector对象中,之后将o引用置空。问题是当o引用被置空后,如果发生GC,我们创建的Object对象是否能够被GC回收呢?答案是否定的。因为,GC在跟踪代码栈中的引用时,会发现v引用,而继续往下跟踪,就会发现v引用指向的内存空间中又存在指向Object对象的引用。也就是说尽管o引用已经被置空,但是Object对象仍然存在其他的引用,是可以被访问到的,所以GC无法将其释放掉。如果在此循环之后,Object对象对程序已经没有任何作用,那么我们就认为此Java程序发生了内存泄漏。
    尽管对于C/C++中的内存泄露情况来说,Java内存泄露导致的破坏性小,除了少数情况会出现程序崩溃的情况外,大多数情况下程序仍然能正常运行。但是,在移动设备对于内存和CPU都有较严格的限制的情况下,Java的内存溢出会导致程序效率低下、占用大量不需要的内存等问题。这将导致整个机器性能变差,严重的也会引起抛出OutOfMemoryError,导致程序崩溃。


一般情况下内存泄漏的避免
在不涉及复杂数据结构的一般情况下,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声明为了实例变量,而不是本地变量。于是,在此函数返回之后,内存中仍然存在整个文件的数据。而很明显,这些数据我们后续是不再需要的,这就造成了内存的无故浪费。
    要避免这种情况下的内存泄露,要求我们以C/C++的内存管理思维来管理自己分配的内存。第一,是在声明对象引用之前,明确内存对象的有效作用域。在一个函数内有效的内存对象,应该声明为local变量,与类实例生命周期相同的要声明为实例变量……以此类推。第二,在内存对象不再需要时,记得手动将其引用置空。

复杂数据结构中的内存泄露问题
则涉及到java中的几种引用方式:强引用,软引用(SoftReference),弱引用(WeakReference),虚引用(PhantomReference),详情参看参考文章【1】。


参考文章:
【1】Java内存泄露的理解与解决
http://www.cnblogs.com/qq78292959/archive/2011/07/25/2116123.html

【2】Java的内存泄漏
http://www.ibm.com/developerworks/cn/java/l-JavaMemoryLeak/

【3】深入理解java的finalize
http://www.iteye.com/topic/484934
分享到:
评论

相关推荐

    Java内存泄露与溢出的区别.doc

    总的来说,理解Java内存泄露和溢出的区别有助于开发者编写更高效、更稳定的代码。通过合理地管理对象生命周期,避免长时间持有无用对象的引用,以及适当地配置JVM的内存参数,可以有效地防止这些问题的发生,提升...

    内存泄露的例子

    常见的Java内存泄露场景包括: 1. 静态集合类:如ArrayList、HashMap等静态变量,它们会一直保有对对象的引用,即使对象本应被回收。 2. 长生命周期的对象持有短生命周期的对象:如线程池中的线程持有大量的对象,...

    基于Java的内存泄露分析及定位

    通过以上内容,我们可以了解到Java内存泄露的基本概念、原理以及如何利用各种工具和技术来进行有效的定位和解决。对于Java开发人员来说,掌握这些知识是非常重要的,它能帮助我们在开发过程中更好地管理内存资源,...

    提高Java开发质量之内存泄露

    #### 二、内存泄露的概念与危害 **概念:** 内存泄露是指在程序运行过程中,对不再使用的对象或资源未能及时释放,导致这些对象继续占用内存空间的现象。在Java中,由于垃圾回收机制的存在,内存泄露的问题不如C/...

    关于static的小结(Java内存溢出)

    在《关于static的小结(Java内存溢出)》这篇文章中,作者主要探讨了与Java中的`static`关键字相关的知识点,以及如何可能导致内存溢出的情况。下面我们将深入分析这些内容。 #### Java中的`static`关键字 `static...

    android应用内存泄露

    因此,了解内存泄露的概念及如何处理这个问题对于每一个Android开发者来说都至关重要。 内存泄露的定义可以这样理解:当应用程序中的一些对象不再被使用,但由于某些原因仍然被系统所保留,即这些对象还被引用着,...

    Java内存分配浅析

    Java内存分配是Java编程中非常重要的概念,它涉及到程序运行时的数据存储和管理。Java程序在JVM(Java Virtual Machine,Java虚拟机)上运行,JVM作为一个平台无关的执行环境,负责Java程序的内存管理和执行。理解...

    深入Java核心_Java内存分配原理精讲

    Java的垃圾回收机制主要负责堆内存的管理,通过自动回收不再使用的对象来避免内存泄露。 2. **栈内存**:主要用于存储基本类型变量和对象引用,以及方法调用时的局部变量。每个线程都有自己的独立栈,执行速度快,...

    Android App定位和规避内存泄露方法研究

    2. 使用Eclipse Memory Analyzer Tool (MAT):MAT是一个强大的内存分析工具,适用于Java层的内存泄露分析。它可以帮助开发者识别内存中大量占用的实例,定位出内存泄露的源头。 规避内存泄露的方法主要包括: 1. ...

    性能测试之内存泄露篇

    本文将详细介绍内存泄露及其与内存溢出的区别,并介绍如何监测和解决这些问题。 **内存泄露**指的是应用程序在运行过程中,对已分配的内存未能正确释放,导致这部分内存无法再次被使用。随着时间的推移,这些未释放...

    java内存分配 内存泄漏

    理解Java内存分配和JVM工作原理对于开发高效、健壮的Java应用至关重要。开发者应避免内存泄漏,合理使用内存,充分利用JVM的垃圾收集机制,同时理解JIT编译的优化策略,以提高程序的运行性能。在开发过程中,使用...

    JavaMemoryLeak内存泄露.doc

    ### Java内存泄露详解 #### 一、Java内存回收机制 Java的一大优势在于其自动化的内存管理,这主要得益于垃圾收集器(Garbage Collector, GC)的存在。GC负责追踪并回收不再使用的对象,使得程序员无需手动释放内存...

    Java内存溢出和内存泄露

    Java内存溢出和内存泄露 Java内存溢出和内存泄露是Java开发中常见的问题,它们之间存在着紧密的联系,了解它们对于编写高质量的Java代码非常重要。 一、为什么要了解内存泄露和内存溢出? 了解内存泄露和内存溢出...

    Android内存泄露检测_mat

    内存泄露是Android应用程序开发中常见的问题,可能导致应用性能下降,用户体验变差,甚至导致应用崩溃。为了有效地检测和解决这些问题,开发者通常会使用各种工具,其中Eclipse Memory Analyzer Tool (MAT)是一个...

    java学习笔记(java 反射机制 流 内存管理)

    Java内存管理主要涉及到堆内存和栈内存的分配与回收。堆内存主要用于存储对象实例,由垃圾收集器自动管理。垃圾收集器通过可达性分析判断对象是否可被访问,不可达的对象将被回收。JVM提供了几种不同的垃圾收集算法...

    JSP+MYSQL+Java类优化分页的实例

    - **close** 方法:用于关闭数据库连接资源,释放内存,避免资源泄露。 ##### comment.jsp 这是一个JSP页面,用于展示评论列表和分页导航。关键点包括: - **页面导入**:导入了必要的Java包,如`java.sql.*`用于...

    java内存模型.pdf

    Java内存模型(Java Memory Model,JMM)是Java虚拟机(JVM)规范的一部分,它定义了共享变量的访问规则和内存操作的细节。Java内存模型在并发编程中非常重要,因为它规定了线程如何和何时可以看到由其他线程修改的...

    java线程池使用后到底要关闭吗

    本文将通过实例代码和详细解释,告诉大家使用完线程池后一定要关闭,否则可能会导致内存泄露和应用崩溃。 首先,让我们了解一下java线程池的基本概念。java线程池是指一种池化技术,用于管理和复用线程,以提高系统...

    疯狂java讲义06 电子版 pdf

    这些知识点涵盖了Java内存管理、对象生命周期、引用变量操作等核心概念,对于希望深入理解Java编程的读者来说是非常宝贵的资料。通过学习这些内容,读者能够更加高效地编写Java程序,更好地管理内存资源。

    java操作redis数据库实例

    本文将详细讲解如何使用Java与Redis进行交互,并提供源码实例。 首先,我们需要了解Redis的基本概念。Redis(Remote Dictionary Server)是一个开源的、基于内存的数据结构存储系统,它可以用作数据库、缓存和消息...

Global site tag (gtag.js) - Google Analytics