美文网首页Effective Java学习
java代码优化——消除过期的对象引用

java代码优化——消除过期的对象引用

作者: Ruheng | 来源:发表于2017-01-21 10:31 被阅读159次

很多人可能在想这么一个问题:Java有垃圾回收机制,那么还存在内存泄露吗?答案是肯定的,所谓的垃圾回收GC会自动管理内存的回收,而不需要程序员每次都手动释放内存,但是如果存在大量的临时对象在不需要使用时并没有取消对它们的引用,就会吞噬掉大量的内存,很快就会造成内存溢出。

一、Java的垃圾回收机制

Java中的对象是在堆中分配,对象的创建有2中方式:new或者反射。对象的回收是通过垃圾收集器,JVM的垃圾收集器简化了程序员的工作,但是却加重了JVM的工作,这是Java程序运行稍慢的原因之一,因为GC为了能正确释放对象,必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,GC都要进行监控,监控对象的状态是为了更加准确、及时地释放对象,而释放对象的根本原则就是该对象不再被引用。

三、Java中的内存泄露

内存泄露的对象有以下两个特点:

① 这些对象是可达的,即在有向图中存在通路可以与其相连。
② 这些对象是无用的,即程序以后都不会再使用这些对象。

public class Stack {  
    private final static int MAX_ATTRIBUTE = 10;  
    private Object[] arr;  
    private int index = 0; 
    public void push(Object obj) {  
        if (index > 9)  
            throw new IllegalArgumentException();  
        arr[index] = obj;  
        index++;  
    }  
    public Stack() {  
        arr = new Object[MAX_ATTRIBUTE];  
    }  
    public Object pop() {  
        if (index < 0)  
            throw new IllegalArgumentException();  
        return arr[--index];  
    }  
}  

这个程序那里发生了内存泄露呢?如果一个栈先增长然后收缩,那么从栈中弹出来的对象将不会被当做垃圾回收,即使使用栈的程序不再引用这些对象,它们也不会被回收,因为栈内部维护这对这些对象的过期引用。

public Object pop() {    
    if (size == 0)    
        throw new EmptyStackException();    
    Object result = elements[--size];    
    elements[size] = null; //Eliminate obsolete reference       
    return result;    
}    

解决办法:只要一个元素被弹出栈,那么就将它的引用置为空,GC就会回收。即一旦数组元素变成了非活动部分的一部分,就手工清空这些数组元素。

不要被类似的问题困扰

当程序员第一次被类似这样的问题困扰的时候,他们往往会过分小心;对于每一个对象引用,一旦不再使用它,就把它清空,这是没有必要的,这样反而会把代码弄的混乱。清空对象的引用应该是一种例外(因为它仅在一些特殊的情况下才需要进行),而不是一种规范行为。消除过期引用最好的办法是让包含该引用的变量结束其生命周期。如果是在最紧凑的作用域范围内定义每一个变量,这种情况就会自然而然地发生。
一般而言,只要类是自己管理内存,就应该警惕内存泄漏问题。一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。

四、常见的内存泄露

① 缓存。一旦你把对象引用放到缓存中,它就很容易被遗忘掉,从而使得它不再有用之后很长一段时间内仍然留在缓存中。
② 在Java程序中,我们经常要和监听器打交道,通常调用诸如addXXXListener()等方法来增加监听器,但往往忘记删除这些监听器,从而增加了内存泄漏的机会。
③ 使用连接池时,除了要显式地关闭连接,还必须显式地关闭Resultset和Statement对象。否则会造成大量的这些对象无法释放,从而引起内存泄露。
④ 尽量少用静态变量,因为静态变量存放在永久代,永久代基本不参与垃圾回收

相关文章

  • java代码优化——消除过期的对象引用

    很多人可能在想这么一个问题:Java有垃圾回收机制,那么还存在内存泄露吗?答案是肯定的,所谓的垃圾回收GC会自动管...

  • 消除过期的对象引用

    第6条:消除过期的对象引用 1. 为什么要消除过期的对象引用 java虽然有自己的垃圾回收机制,但是并没有那么的智...

  • 消除过期的对象引用

    你能看出以下代码哪里内存泄漏吗? 答案是: pop()方法存在内存泄漏。 内存泄漏可以称为“ 无意识的对象保持(u...

  • 消除过期的对象引用

    什么是过期的对象引用? 我们通过简单的栈实现来引入过期的对象引用。 实际上,这段程序中并没有很明显的错误。无论如何...

  • 消除过期的对象引用

    某些类内部维护着对象的过期引用(指永远也不会再被解除的引用),这些对象不会被当作垃圾回收,产生了内存泄露(这类内存...

  • 消除过期的引用对象

    C或者C++是手工管理内存语言,java语言是自带垃圾回收,程序员的工作就很容易,因为当你用完了对象之后,他会被自...

  • [Effective Java] (06)消除过期的对象引用

    虽然在Java语言中拥有垃圾收集(GC)回收程序,在创建对象后,不用程序员手动回收对象,但在某些情况下依然会造成内...

  • 1.7消除过期的对象引用

    1.7消除过期的对象引用 1.7.1 ​ 以下代码并没有明显的错误,无论如何测试,它都会成功通过每一项测...

  • 消除过期的对象的引用

    一、消除过期的对象的引用的好处 好处1、防止内存泄漏,导致磁盘交换,甚至会导致程序失败好处2、如果错误地解除引用,...

  • Effective Java 第二章

    避免创建不必要的对象 优先考虑使用基本类型而不是装箱类型,要当心无意识的自动装箱 消除过期对象的引用 一旦对象引用...

网友评论

    本文标题:java代码优化——消除过期的对象引用

    本文链接:https://www.haomeiwen.com/subject/obwgbttx.html