小心内存泄漏

本文阅读 3 分钟
首页 代码,Java 正文

看完这本《Effective Java》,我悟了

7 消除过期的对象引用

这一条建议主要讲的是要规避内存泄漏。因为像Java这种具有垃圾回收机制的语言,内存泄漏一般都是比较隐蔽的。

例如:

package com.wjw;

import java.util.Arrays;
import java.util.EmptyStackException;

/** * 2 * @Author: 小王同学 * 3 * @Date: 2021/11/23 20:50 * 4 */
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);
    }

}

上述代码中存在着内存泄漏,如果向栈中先添加元素再弹出元素,弹出来的对象不会被回收,因为栈内部维护着弹出对象的过期引用。

解决这个问题很简单,将出栈元素的引用设为过期即可: img

内存泄漏的其他来源:

  • 缓存 原因是被放入缓存的对象引用容易被我们遗忘。利用缓存中存储数据的价值与存储时间的长短成反比的特点,可以开一个后台线程及时清理掉失效项。
  • 监听器和其他回调 原因是客户端在我们提供的API中注册回调,但却没有取消回调时,它们就会堆积起来。如果我们希望回调立即被回收的话可以只保留它们的弱引用(WeakHashMap中的键)。

这里还要补充一点关于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
本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://wangjiawei.blog.csdn.net/article/details/121626310
-- 展开阅读全文 --
安全面试之XSS(跨站脚本攻击)
« 上一篇 07-24

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复