Effective Java - 创建和销毁对象 - 消除过期的对象引用

本文通过一个经典的栈实现案例,分析了Java中常见的内存泄漏原因及其解决办法,包括过期引用、缓存管理和监听器等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

effective java
读书笔记 仅供参考

Java 一个很重要的特色就是垃圾回收,但是它也不是万能的,有兴趣的可以阅读《深入理解 Java 虚拟机》

一段经典的内存泄漏案例

public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    public Stack() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY ];
    }
    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }

    pubic Object pop() {
        if(size == 0) {
            throw new EmptyStackException();
        }
        return element[--size];
    }

    private void ensureCapacity() {
        if(elements.length == size) {
            elements = Arrays.copyOf(elements, 2 * size + 1);
        }
    }
}

上面这段程序写了一个栈的出栈和入栈,表面上没有问题,但是在长时间运行后,会有出现内存泄漏的可能。
主要问题就在 pop() 方法上,在出栈时,只是将 size 减少,但是没有将引用消除。Java 的引用有四种:强引用,弱引用,软引用和虚引用(关于引用)。上述的就是采用强引用(在 Java 的编写中基本都是使用强引用,个人而言),所以在使用强引用时,即时内存空间不足,垃圾回收器也不会清理这些对象,而是抛出 OutOfMemoryError。
上面所说的就是过期引用:永远不会被解除的引用。

修复方法

    pubic Object pop() {
        if(size == 0) {
            throw new EmptyStackException();
        }
        Object result = element[--size];
        element[size] = null;
        return result;
    }

这样做的另一个好处:如果以后被错误的引用,会抛出 NPE 异常。

消除过期引用最好的方法时在最紧凑的作用域范围内定义每一个变量

内存泄漏第一来源

就是上面所说的过期引用,只要是自己管理内存,就应该警惕内存泄漏问题。

内存泄漏第二来源

缓存。
缓存应该时不时的清除掉没用的项,现在不少缓存工具都具有定时功能

内存泄漏第三来源

监听器和其他回调
确保回调立即被当中垃圾回收的最佳方法时只保存弱引用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值