SoftReference WeakReference区别避免混淆 软引用和弱引用的不同从源码注释入手以及手写测试避免记错混淆使用谐音记忆法加深印象

我的app很头疼,
有时候很容易记混淆,搞不懂哪个是内存不足才会回收,哪个随时可能被回收 哪个调用gc之后一定会回收,哪个是安卓推荐使用的..

那么先从安卓的源码开始,打开源码发现有一段注释证明软引用不推荐使用,

SoftReference

SoftReference的类注释:

 * Soft reference objects, which are cleared at the discretion of the garbage
 * collector in response to memory demand.
 *
 * <p> Suppose that the garbage collector determines at a certain point in time
 * that an object is <a href="package-summary.html#reachability">softly
 * reachable</a>.  At that time it may choose to clear atomically all soft
 * references to that object and all soft references to any other
 * softly-reachable objects from which that object is reachable through a chain
 * of strong references.  At the same time or at some later time it will
 * enqueue those newly-cleared soft references that are registered with
 * reference queues.
 *
 * <p> All soft references to softly-reachable objects are guaranteed to have
 * been cleared before the virtual machine throws an
OutOfMemoryError .  Otherwise no constraints are placed upon the
 * time at which a soft reference will be cleared or the order in which a set
 * of such references to different objects will be cleared.  Virtual machine
 * implementations are, however, encouraged to bias against clearing
 * recently-created or recently-used soft references.
 *
 * <h3>Avoid Soft References for Caching</h3>
 * In practice, soft references are inefficient for caching. The runtime doesn't
 * have enough information on which references to clear and which to keep. Most
 * fatally, it doesn't know what to do when given the choice between clearing a
 * soft reference and growing the heap.
 *
 * <p>The lack of information on the value to your application of each reference
 * limits the usefulness of soft references. References that are cleared too
 * early cause unnecessary work; those that are cleared too late waste memory.
 *
 * <p>Most applications should use an {@code android.util.LruCache} instead of
 * soft references. LruCache has an effective eviction policy and lets the user
 * tune how much memory is allotted.
 *
 * @author   Mark Reinhold
 * @since    1.2
 */

从上面有几个关键英文单词
Avoid Soft References for Caching
Most applications should use an {@code android.util.LruCache}
避免使用, 大部分应用应该使用LruCache 这里说的很清楚,不是绝对,一定,不是必须使用LruCache, fragment的存储缓存是无法知道大小的,LruCache 我是不知道怎么整,翻阅了百度也找不到任何答案,测量obj大小的方法 也被谷歌删除了.fragment的存储到底用哪个好呢?

避免使用缓存缓存的软引用
*实际上,软引用对于缓存是无效的。运行时没有足够的信息,说明哪些要明确,哪些要保留。最
*致命的

All soft references to softly-reachable objects are guaranteed to have
 * been cleared before the virtual machine throws an
 * <code>OutOfMemoryError</code>.  O

guaranteed 保证
虚拟机保证在内存不足之前清理所有Soft references,我英语不好,应该是说内存不足的时候才会清除?还是说内存不足的时候一定会清除,但是不足的时候清除不清除呢?

WeakReference

注释:


/**
 * Weak reference objects, which do not prevent their referents from being
 * made finalizable, finalized, and then reclaimed.  Weak references are most
 * often used to implement canonicalizing mappings.
 *
 * <p> Suppose that the garbage collector determines at a certain point in time
 * that an object is weakly reachable</a>.  At that time it will atomically clear all weak references to
 * that object and all weak references to any other weakly-reachable objects
 * from which that object is reachable through a chain of strong and soft
 * references.  At the same time it will declare all of the formerly
 * weakly-reachable objects to be finalizable.  At the same time or at some
 * later time it will enqueue those newly-cleared weak references that are
 * registered with reference queues.
 *

 */

软引用验证,只有内存不足才会回收 如果回收了还是内存不足就鸡鸡了,这很适合用在fragment的缓存,因为内存还足够没必要回收.

下面是我测试SoftReference的程序,用eclipse测试最好不过了,调整最大内存为2M,初始化内存也为2M

改配置感受 紧

  Launch configurations for 'TestReference.java'  ->Argments选项卡  Vm argments里面填写参数-Xmx2m -xms2m 
image.png

测试软引用源代码

    /**
     *Launch configurations for 'TestReference.java'  ->Argments选项卡  Vm argments里面填写参数-Xmx2m -xms2m   
     * @param args
     */
    public static void main(String[] args) {
        Object referent = new Object();
        java.util.List<String[]> list = new ArrayList<>();
        SoftReference<Object> softRerference = new SoftReference<Object>(referent);

        assertNotNull(softRerference.get());

        referent = null;

        int count = 0;
    
        while (softRerference.get()!=null) {
            System.out.println("obj!=null count:" + count);
            count++;
            String[] current=new String[1000];
            System.out.println("isempty:"+(softRerference.get()==null));
            list.add(current);
            for (int i = 0; i < current.length; i++) {
                
                current[i]=i+"";
            }
            
        
                        if(count%1000==0){
                        }
        }
        
        System.out.println("obj is recycle");

        /**
         * soft references 只有在 jvm OutOfMemory 之前才会被回收, 如果回收后发现还是内存不足,那么蛋蛋了
         * Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
    at java.util.Arrays.copyOfRange(Arrays.java:3664)
    at java.lang.String.<init>(String.java:207)
    at java.lang.StringBuilder.toString(StringBuilder.java:407)
    at TestReference.main(TestReference.java:29)
         * 
         */
        
    }

弱引用测试

    static class MyObj {
        public MyObj(int no) {
            this.no = no;
        }

        public String[] getCurrent() {
            return current;
        }

        public void setCurrent(String[] current) {
            this.current = current;
        }

        public int getNo() {
            return no;
        }

        public void setNo(int no) {
            this.no = no;
        }

        String[] current = new String[1000];
        int no;

        @Override
        protected void finalize() throws Throwable {
            System.out.println("from:"+no+" :我被回收了我是hasCode:" + hashCode());
            super.finalize();
        }
    }

    /**
     *Launch configurations for 'TestReference.java'  ->Argments选项卡  Vm argments里面填写参数-Xmx2m -xms2m   
     * @param args
     */
    public static void main(String[] args) {
        Object referent = new Object();
        java.util.List<WeakReference<MyObj>> list = new ArrayList<>();
        int loopindex = 0;
    System.err.println("=================================弱引用测试=================================");
            while(loopindex<200){
                
                String[] current=new String[500];
                for (int i = 0; i < current.length; i++) {
                    
                    current[i]=i+"";
                }
                MyObj obj=new MyObj(loopindex);
                obj.setCurrent(current);
                list.add(new WeakReference<TestReference.MyObj>(obj));
                if(loopindex%5==0&&loopindex>0){
                    System.out.println("start================"+loopindex+"================================");
                    System.out.println("即将调用调用主动gc,刚刚放进去的对象index:"+loopindex+"还在否:"+list.get(loopindex).get());
                    System.gc();
                    System.out.println("主动调用gc");
                    System.out.println("调用之后刚刚放进去的对象index:"+loopindex+"还在否:"+list.get(loopindex).get());
                    System.out.println("调用之后第一个还在否:"+list.get(0).get());
                    System.out.println("end================"+loopindex+"================================");
                }
                loopindex++;
            }
            
        
        

        /**

         * 
         */
        
    }

输出结果:

=================================弱引用测试=================================
start================5================================
即将调用调用主动gc,刚刚放进去的对象index:5还在否:TestReference$MyObj@6d06d69c
主动调用gc
调用之后刚刚放进去的对象index:5还在否:TestReference$MyObj@6d06d69c
调用之后第一个还在否:null
end================5================================
from:2 :我被回收了我是hasCode:1113044619
from:3 :我被回收了我是hasCode:1284526257
from:4 :我被回收了我是hasCode:1219485179
from:1 :我被回收了我是hasCode:229464714
from:0 :我被回收了我是hasCode:1915835994
start================10================================
即将调用调用主动gc,刚刚放进去的对象index:10还在否:TestReference$MyObj@7852e922
主动调用gc
调用之后刚刚放进去的对象index:10还在否:TestReference$MyObj@7852e922
调用之后第一个还在否:null
end================10================================
from:9 :我被回收了我是hasCode:1022006645
from:8 :我被回收了我是hasCode:178046742
from:7 :我被回收了我是hasCode:1837278661
from:6 :我被回收了我是hasCode:368688553
from:5 :我被回收了我是hasCode:1829164700
start================15================================
即将调用调用主动gc,刚刚放进去的对象index:15还在否:TestReference$MyObj@4e25154f
主动调用gc
from:10 :我被回收了我是hasCode:2018699554
调用之后刚刚放进去的对象index:15还在否:TestReference$MyObj@4e25154f
from:14 :我被回收了我是hasCode:2102444894
调用之后第一个还在否:null
from:13 :我被回收了我是hasCode:295178133
from:12 :我被回收了我是hasCode:1774992622
from:11 :我被回收了我是hasCode:822136971
end================15================================
start================20================================

测试调节初始化数组大小为500 或者1000 如果是1千,我们发现即使没有调用System.gc()它已经开始进行回收了,也就是稍微吃紧就会回收了,而改成500之后 第一次loop,没有回收等到调用gc执行完毕start-end逻辑后, 3 ,4,2,1,0都一个一个被回收了,从这里的消息也可以看出,回收虽然不会超大概率回收刚刚放进去的,但是也不会百分百先回收第一个,或者也许是日志打印和本地native消息不同步导致的??

看上去好像差不多,意思是在不定期检测 弱引用对象,那些不可达的进行清除.
但是没有说内存不足``oom```之前弱引用对象就一定已经被清除了。。

WeakHashMap 对于集合来说,用WeakHashMap也许更方便

软引用 手动调用System.gc回收的时候软引用不一定会回收, 但是弱引用一定会被回收,所以你是打算用软引用还是用弱引用呢?

为了加深印象避免混淆,我打算给他们取一个名字 ,软足弱鸡g ,也就是软引用是内存不足才会瘦 ,弱引用 gc马上会瘦
参考链接
http://san-yun.iteye.com/blog/1683558
https://baijiahao.baidu.com/s?id=1578867464445861486&wfr=spider&for=pc
http://www.cnblogs.com/skywang12345/p/3154474.html
测试案例参考
http://wiseideal.iteye.com/blog/1469295

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容