美文网首页
java 弱引用的内存泄漏模拟 及解决方案 参考ThreadL

java 弱引用的内存泄漏模拟 及解决方案 参考ThreadL

作者: jalen2024 | 来源:发表于2022-02-24 08:00 被阅读0次

    下面这个Demo可以复现内存泄漏的场景.
    从打印的日志可以看到在我们手动GC之后,Entry里面的value还是没有被回收。

    package com.jalen.android.memoryLeak;
    
    import java.lang.ref.WeakReference;
    import java.util.Arrays;
    
    /**
     * 测试弱引用的内存泄漏 参考ThreadLocalMap
     */
    public class TestWeakReference {
    
    
        public static void main(String[] args) {
            MyWeakMap myWeakMap = new MyWeakMap();
            myWeakMap.put(0, new String("a"), "1");
            myWeakMap.put(1, new String("b"), "2");
            myWeakMap.put(2, new String("c"), "3");
            myWeakMap.put(3, new String("d"), "4");
            System.out.println(myWeakMap); //[a:1, b:2, c:3, d:4]
            System.gc();
            System.out.println(myWeakMap.get("a"));//null
            System.out.println(myWeakMap.get("b"));//null
            System.out.println(myWeakMap.get("c"));//null
            System.out.println(myWeakMap.get("d"));//null
            System.out.println(myWeakMap);//[null:1, null:2, null:3, null:4]
        }
    
    
        static class MyWeakMap {
    
            Entry[] table = new Entry[4];
    
            public void put(int index, String key, String value) {
                table[index] = new Entry(key, value);
            }
    
            public String get(String key) {
                for (Entry entry : table) {
                    if (entry != null) {
                        String k = entry.get();
                        if (null != k && k.equals(key)) {
                            return entry.value;
                        }
                    }
                }
                return null;
            }
    
            @Override
            public String toString() {
                return Arrays.toString(table);
            }
    
            static class Entry extends WeakReference<String> {
    
                String value;
    
                public Entry(String referent, String value) {
                    super(referent);
                    this.value = value;
                }
    
                @Override
                public String toString() {
                    return get() + ":" + value;
                }
            }
        }
    
    
    }
    

    针对以上的场景我们可以通过ReferenceQueue可以监测到内存的泄漏,
    在手动GC回收之后我们再次手动clean了一次,
    在clean方法里通过queue去查找未被回收的对象,对里面的对象进行置空 释放内存。

    package com.jalen.android.memoryLeak;
    
    import java.lang.ref.ReferenceQueue;
    import java.lang.ref.WeakReference;
    import java.util.Arrays;
    
    /**
     * 测试弱引用的内存泄漏 参考ThreadLocalMap
     */
    public class TestWeakReferenceQueue {
    
    
        public static void main(String[] args) {
            MyWeakMap myWeakMap = new MyWeakMap();
            myWeakMap.put(0, new String("a"), "1");
            myWeakMap.put(1, new String("b"), "2");
            myWeakMap.put(2, new String("c"), "3");
            myWeakMap.put(3, new String("d"), "4");
            System.out.println(myWeakMap);//[a:1, b:2, c:3, d:4]
            System.gc();
            System.out.println("手动GC之后");
            System.out.println(myWeakMap.get("a"));//null
            System.out.println(myWeakMap.get("b"));//null
            System.out.println(myWeakMap.get("c"));//null
            System.out.println(myWeakMap.get("d"));//null
            System.out.println(myWeakMap);//[null:1, null:2, null:3, null:4]
            System.out.println("手动clean之前");
            myWeakMap.clean();
            System.out.println("手动clean之后");//[null, null, null, null]
            System.out.println(myWeakMap);
        }
    
    
        static class MyWeakMap {
            static ReferenceQueue queue = new ReferenceQueue();
            Entry[] table = new Entry[4];
    
            public void put(int index, String key, String value) {
                table[index] = new Entry(key, value);
            }
    
    
            public void clean() {
                Object ref;
                while ((ref = queue.poll()) != null) {
                    System.out.println(ref);
                    for (int i = 0; i < table.length; i++) {
                        if (table[i] == ref) {
                            table[i] = null;
                        }
                    }
                }
            }
    
    
            public String get(String key) {
                for (Entry entry : table) {
                    if (entry != null) {
                        String k = entry.get();
                        if (null != k && k.equals(key)) {
                            return entry.value;
                        }
                    }
                }
                return null;
            }
    
            @Override
            public String toString() {
                return Arrays.toString(table);
            }
    
            static class Entry extends WeakReference<String> {
    
                String value;
    
                public Entry(String referent, String value) {
                    super(referent, queue);
                    this.value = value;
                }
    
                @Override
                public String toString() {
                    return get() + ":" + value;
                }
            }
        }
    
    
    }
    

    相关文章

      网友评论

          本文标题:java 弱引用的内存泄漏模拟 及解决方案 参考ThreadL

          本文链接:https://www.haomeiwen.com/subject/mbfzlrtx.html