Java weak reference memory leak simulation and solution refer to ThreadLocalMap

The following Demo can reproduce the memory leak scenario.
From the printed log, we can see that after we manually GC, the value in the Entry is still not recycled.

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;
            }
        }
    }


}

For the above scenarios, we can monitor memory leaks through ReferenceQueue.
After manual GC recycling, we manually clean it again.
In the clean method, we use the queue to find objects that have not been recycled, and empty the objects inside to release the memory. .

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;
            }
        }
    }


}

Guess you like

Origin blog.csdn.net/admin_jalen/article/details/123103265