《Effective java》读书笔记2——内存泄漏

本文通过分析一个典型的Java内存泄漏例子,展示了在使用数组实现Stack栈数据结构时可能导致的内存持续增长问题,并详细解释了其原因及解决办法。重点强调了如何避免在长生命周期的集合容器中留下无效引用,以及对于通用资源服务、监听器和回调函数的正确处理方式。

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

JVM提供了垃圾回收器,java程序员再也不用想C/C++程序员一样整天为对象的清理工作而焦头烂额,但是并非说Java中不存在内存泄漏的情况,下面展示一个典型的内存溢出例子。

使用数组作为底层数据结构实现一个Stack栈数据结构的容器,代码如下:

public class Stack{
	private Object[] elements;
	private int size = 0;
	private static final int DEFAULT_SIZE = 15;
	public Stack(){
	elements = new Object[DEFAULT_SIZE];
}
public void push(Object o){
	ensureCapatity();
	elements[size++] = o;
}
public Object pop(){
	if(size == 0){
	throw new EmptyStackException();
}
return elements[--size];
}
//如果栈已满,则将容量扩大一倍
public ensureCapatity(){
	if(elements.length == size){
	elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
}

咋一看可能看不出什么问题,相信很多人也写过这样的代码,如果使用大量数据测试就会发现内存持续上升,如果把测试数据增大一倍,发现内存也跟着增长一倍,这就产生了典型的内存泄漏情况。仔细研究出栈pop()操作你会发现,栈中存在大量的无法被引用到的对象,因为出栈之后并没有将元素标记为不再使用,这些在size之后的元素就成了无法被访问的无效引用对象,但是由于stack栈对象本身还是有效引用,因此这些无效的引用无法被垃圾回收器回收,造成内存泄漏。

解决上述例子内存泄漏的方法也很简单,重新pop()方法如下:

public Object pop(){
	if(size == 0){
	throw new EmptyStackException();
}
Object result = elements[--size];
elements[size] = null;//将已经出栈的元素置为null,垃圾回收器就会清理这些对象
return result;
}

Java中经常引起内存泄漏的情况及解决方法:

(1).长生命周期的集合容器对象中存在大量无效引用的短生命元素对象:将容器中不再使用的对象标记为null,以防止产生无法访问的无效引用。

(2).通用的资源服务,如namingservice,cache等等:定时清理;使用WeakReference弱引用;使用WeakHashMap容器等。

(3).监听器和callback回调函数。使用WeakReference弱引用;使用WeakHashMap容器等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值