• 强软弱虚引用试验


    一、强引用

    代码:

    package top.gabin.concurrent.reference;
    
    /**
     * 强引用
     * -XX:+PrintGC -Xms11m -Xmx11m
     * 
     */
    public class StrongReference {
        public static void main(String[] args) {
            // 分配10M,
            byte[] bytes = new byte[1024 * 1024 * 10];
            // 使用默认的PN+PO直接oom了
        }
    }

    日志:

    [GC (Allocation Failure)  1626K->520K(11776K), 0.0008186 secs]
    [GC (Allocation Failure)  520K->536K(11776K), 0.0010718 secs]
    [Full GC (Allocation Failure)  536K->392K(11776K), 0.0080720 secs]
    [GC (Allocation Failure)  392K->392K(11776K), 0.0016596 secs]
    [Full GC (Allocation Failure)  392K->375K(11776K), 0.0063991 secs]
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at top.gabin.concurrent.reference.StrongReference.main(StrongReference.java:12)

    原来以为都一样吧,然后试了一把G1垃圾回收器,结果会执行垃圾回收,不会报错

    代码:

    package top.gabin.concurrent.reference;
    
    /**
     * 强引用
     * -XX:+PrintGC -Xms11m -Xmx11m -XX:+UseG1GC
     */
    public class StrongReference {
        public static void main(String[] args) {
            // 分配10M,
            byte[] bytes = new byte[1024 * 1024 * 10];
            // 原来以为到不了这里,结果发现G1如果把bytes变量设置为null,会触发垃圾回收,不会直接oom
            bytes = null;
            bytes = new byte[1024 * 1024 * 1];
            System.out.println(bytes);
        }
    }

    打印日志:

    [GC pause (G1 Humongous Allocation) (young) (initial-mark) 1770K->592K(12M), 0.0027535 secs]
    [GC concurrent-root-region-scan-start]
    [GC pause (G1 Humongous Allocation) (young)[GC concurrent-root-region-scan-end, 0.0006785 secs]
    [GC concurrent-mark-start]
     592K->518K(12M), 0.0023798 secs]
    [GC concurrent-mark-end, 0.0018801 secs]
    [GC remark, 0.0012885 secs]
    [GC pause (G1 Evacuation Pause) (young)-- 10M->518K(12M), 0.0070966 secs]
    [GC cleanup 621K->621K(12M), 0.0004545 secs]
    [B@60e53b93

    参考main方法的二进制码(解析后的)

     0 ldc #2 <10485760>
     2 newarray 8 (byte)
     4 astore_1
     5 aconst_null
     6 astore_1
     7 ldc #3 <1048576>
     9 newarray 8 (byte)
    11 astore_1
    12 getstatic #4 <java/lang/System.out>
    15 aload_1
    16 invokevirtual #5 <java/io/PrintStream.println>
    19 return

    二、软应用

    应用场景:缓存,不过目前应该比较少用java做缓存

     代码:

    ackage top.gabin.concurrent.reference;
    
    import java.lang.ref.SoftReference;
    
    /**
     * 运行参数:-XX:+PrintGC -Xms11m -Xmx11m -XX:+UseG1GC
     * 软应用在内存不够用的时候会触发垃圾回收
     */
    public class SoftReferenceTest {
    
        public static void main(String[] args) {
            SoftReference<byte[]> softReference0 = new SoftReference<>(new byte[1024 * 1024 * 6]);
            SoftReference<byte[]> softReference1 = new SoftReference<>(new byte[1024 * 1024 * 6]);
            System.out.println(softReference0.get() + "
    "); //
            System.out.println(softReference1.get() + "
    "); // 不为空,证明内存不够用的时候会被回收
        }
    
    }

    日志:

    [GC pause (G1 Humongous Allocation) (young) (initial-mark) 1753K->544K(12M), 0.0027674 secs]
    [GC concurrent-root-region-scan-start]
    [GC concurrent-root-region-scan-end, 0.0005636 secs]
    [GC concurrent-mark-start]
    [GC concurrent-mark-end, 0.0001255 secs]
    [GC remark, 0.0017976 secs]
    [GC cleanup 6688K->6688K(12M), 0.0004628 secs]
    [GC pause (G1 Humongous Allocation) (young) 6893K->6663K(12M), 0.0053371 secs]
    [Full GC (Allocation Failure)  6663K->6524K(12M), 0.0046775 secs]
    [Full GC (Allocation Failure)  6524K->363K(12M), 0.0043229 secs]
    null
    
    [B@60e53b93

    注意Full GC触发了两次,第一次是不回收的,第二次才回收的。

    三、弱引用

    应用场景:ThreadLocal线程变量中,源码还没看太明白,大概就是为了避免内存泄露

    public T get() {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null) {
                ThreadLocalMap.Entry e = map.getEntry(this);
                if (e != null) {
                    @SuppressWarnings("unchecked")
                    T result = (T)e.value;
                    return result;
                }
            }
            return setInitialValue();
        }
    static class Entry extends WeakReference<ThreadLocal<?>> {
                /** The value associated with this ThreadLocal. */
                Object value;
    
                Entry(ThreadLocal<?> k, Object v) {
                    super(k);
                    value = v;
                }
            }

     代码:

    package top.gabin.concurrent.reference;
    
    import java.lang.ref.WeakReference;
    
    /**
     * 运行参数:-XX:+PrintGC -Xms11m -Xmx11m -XX:+UseG1GC
     */
    public class WeakReferenceTest {
        public static void main(String[] args) {
            WeakReference<byte[]> weakReference = new WeakReference<>(new byte[1024 * 1024 * 5]);
            System.out.println(weakReference.get());
            System.gc();
            System.out.println(weakReference.get());
        }
    }

    日志:

    [B@60e53b93
    [Full GC (System.gc())  7033K->399K(12M), 0.0072117 secs]
    null

    四、虚引用

    应用场景:目前知道的应该是在jdk中对直接内存进行回收使用,因为直接内存无法直接被垃圾回收器回收,只能通过UNSAFE做内存管理

    代码:

    package top.gabin.concurrent.reference;
    
    import java.lang.ref.PhantomReference;
    import java.lang.ref.ReferenceQueue;
    
    /**
     * 运行参数:-XX:+PrintGC -Xms11m -Xmx11m -XX:+UseG1GC
     */
    public class PhantomReferenceTest {
        public static void main(String[] args) {
            ReferenceQueue linkedList = new ReferenceQueue<>();
            PhantomReference<byte[]> reference = new PhantomReference<byte[]>(new byte[1024 * 1024 * 6], linkedList);
            // 没回收也取不到,是NULL,虚引用的主要作用在于第二个参数,gc之后,ReferenceQueue会有被回收的对象
            System.out.println(reference.get());
            System.gc();
            // 队列里面会有被回收的对象
            System.out.println(linkedList.poll());
        }
    }

    日志:

    [GC pause (G1 Humongous Allocation) (young) (initial-mark) 1753K->552K(12M), 0.0040210 secs]
    [GC concurrent-root-region-scan-start]
    [GC concurrent-root-region-scan-end, 0.0009247 secs]
    [GC concurrent-mark-start]
    [GC concurrent-mark-end, 0.0000387 secs]
    [GC remark, 0.0023809 secs]
    [GC cleanup 6696K->6696K(12M), 0.0006334 secs]
    [Full GC (System.gc())  6798K->6524K(12M), 0.0028324 secs]
    null
    java.lang.ref.PhantomReference@60e53b93
  • 相关阅读:
    十二招让你的电脑桌变得更舒适
    【看后请推荐】程序员接私单不传秘籍之一二合编:加料更新!一定要看!
    【看后请推荐】程序员接私单不传秘籍之二:单子从哪儿来?
    【看后请推荐】程序员接私单不传秘籍之一:准备工作
    【看完请推荐】记国庆前的一次码农受骗记
    优化MySQL,还是使用缓存?读一篇文章有感
    大数据下Limit使用(MySQL)
    类Unix平台程序调试
    STL学习笔记
    MFC学习笔记
  • 原文地址:https://www.cnblogs.com/gabin/p/13618691.html
Copyright © 2020-2023  润新知