java 是垃圾回收语言, 但有些对象因为我们的实际代码行为, 无法被jvm 判定可以被回收, 因此这些特殊的对象需要手动清理无法直接被回收的对象, 需要手动处理典型例子 ,以下的例子中. 数组或者 List 或者 Map 中可能有些对象已经无用,但我们不手动移除的话, 他们一直会存在于容器中, 造成垃圾无法被回收class A{ private static B[] b2 = new B[16] ;MapList}
要理解这个问题, 需要理解 jvm 的垃圾回收机制. 这里说的就是因为一些疏忽操作或定义, 导致了部分数据一直无法被回收。这里可能对性能拖累不严重,但是却会占用更多资源,严重者导致oom。
资源未关闭问题,有些随着gc可能会被回收,有些则持续占用,但无论哪种,都可能严重拖累系统性能
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;
}
public Object pop(){
if (size == 0)
throw new EmptyStackException();
return elements[-- size];
}
private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
上述代码中存在着内存泄漏,如果向栈中先添加元素再弹出元素,弹出来的对象不会被回收,因为栈内部维护着弹出对象的过期引用。
解决这个问题很简单,将出栈元素的引用设为过期即可:
这里还要补充一点关于WeakHashMap的知识:WeakHashMap其实是一种弱引用Map,key会存储为弱引用,当GC时,如果这些key没有外部强引用存在的话(当回调对应的强引用被不存在了时),就会被垃圾回收掉。它的这个特性也多被用来实现缓存,如果外面对某个key的引用不存在了,缓存中key对应的这一项就会被自动删除。
例如:使用
WeakHashMap
存储BigImage实例,key是ImageName类型,value是BigImage实例,如果令
imageName = null
,这样就没有强引用指向这一个key了,BigImage实例就会在GC时被回收掉
WeakHashMap<UniqueImageName, BigImage> map = new WeakHashMap<>();
BigImage bigImage = new BigImage("image_id");
UniqueImageName imageName = new UniqueImageName("name_of_big_image"); // 强引用
map.put(imageName, bigImage);
assertTrue(map.containsKey(imageName));
imageName = null; //map中的values对象成为弱引用对象
System.gc(); //主动触发一次GC