关于程序员:查漏补缺强软弱虚引用

39次阅读

共计 3553 个字符,预计需要花费 9 分钟才能阅读完成。

强援用

  • 强援用:Object o = new Object()
  • 软援用:new SoftReference(o);
  • 弱援用:new WeakReference(o);
  • 虚援用:new PhantomReference(o,Queue);

本次会用到命令 -XX:+PrintGCDetails
会打印

[GC (Allocation Failure) [PSYoungGen: 29680K->4080K(29696K)] 73163K->72619K(98304K), 0.0245660 secs] [Times: user=0.15 sys=0.02, real=0.03 secs] 


[Full GC (Ergonomics) [PSYoungGen: 4080K->3557K(29696K)] [ParOldGen: 68539K->68498K(68608K)] 72619K->72055K(98304K), [Metaspace: 8977K->8977K(1056768K)], 0.1491246 secs] [Times: user=1.02 sys=0.01, real=0.15 secs] 

援用类型 什么时候回收
强援用 强援用的对象,只有 GC root 可达,不会被回收,内存不够用了,会抛出 oom
软援用:SoftReference 软援用对象,GC root 中,只有软援用能够达到某个对象 a,在 oom 之前,垃圾回收会回收对象 a
弱援用:WeakReference 弱援用,GC root 中,youngGC 就回回收 c
虚援用:PhantomReference 虚援用,必须配合 ReferenceQueue 应用,代替 finalize

强援用

强援用就是咱们最罕用的创建对象的形式 Object o = new Object(),只有援用还在,就不会被回收,堆内存占满就间接抛出 OOM。然而当指向null 后,在 gc 时就回回收对应内存

//        Thread.sleep(10000);
//        strongReference();
//        -XX:+PrintGCDetails -Xms100m -Xmx100m
    private static void strongReference() throws InterruptedException {
        int size=100000;
        Element[] arr= new Element[size];
        try{for (int i = 0; i < size; i++) {arr[i]=new Element(i);
                Thread.sleep(1);
                //arr[i]=null;
            }
        }catch (Throwable e){for (int i = 0; i < size; i++) {if(arr[i]==null){System.out.println("null number:"+i);//null number:84318
                    break;
                }
            }
        }
    }

如果执显式设置为 null

软援用

软援用,应用 SoftReference 创立,然而,当内存不够的时候,回把对象回收,not null number:139479,整个程序执行,并无产生 oom。

源代码正文中写了在抛出 oom 之前革除,通过 PrintGCDetails 也能够看到,根本都是在 FullGC 中解决,联合 visualVM 能够看到,并不是所有 FullGC 都会解决,一半都是堆内存占用快满了,才会触发

All soft references to softly-reachable objects are guaranteed to have
 * been cleared before the virtual machine throws an
 * <code>OutOfMemoryError</code>
    public static void main(String[] args) throws Exception {Thread.sleep(10000);
//        strongReference();
        softReference();}

    private static void softReference() throws InterruptedException {
        int size=200000;
        SoftReference<Element>[] list=new SoftReference[size];


        for (int i = 0; i < size; i++) {list[i]=new SoftReference<Element>(new Element(i));
            Thread.sleep(1);
        }
        for (int i = 0; i < size; i++) {if(list[i].get()!=null){System.out.println("not null number:"+i);
                break;
            }

        }
    }

弱援用

弱援用,调用形式和下面差不多,就是类换成了 WeakReference,其余一律没有变,功过图能够看到它是在YoungGC 的时候就革除了

    private static void weakReference() throws InterruptedException {
        int size=200000;
        WeakReference<Element>[] list=new WeakReference[size];


        for (int i = 0; i < size; i++) {list[i]=new WeakReference<Element>(new Element(i));
            Thread.sleep(1);
        }
        for (int i = 0; i < size; i++) {if(list[i].get()!=null){System.out.println("not null number:"+i);
                break;
            }

        }
    }

虚援用

PhantomReference和下面三个不大一样,我一开时认为也是不便清理,可是看了正文不大一样。

PhantomReference最罕用于以一种比 Java finalization 更灵便的形式来调度预剖析清理操作。

Phantom
 * references are most often used for scheduling pre-mortem cleanup actions in
 * a more flexible way than is possible with the Java finalization mechanism.

也就是说它设计的目标就是为了代替finalize

    private static void phantomReference() throws InterruptedException {Element e=new Element(1);
        ReferenceQueue referenceQueue=new ReferenceQueue();

        PhantomReference<Element> reference=new PhantomReference(e,referenceQueue){
            @Override
            public void clear() {System.out.println(1111111);
                super.clear();}
        };

        new Thread(){
            @Override
            public void run() {while (true){
                    try {PhantomReference reference1= (PhantomReference) referenceQueue.remove();
                        reference1.clear();} catch (InterruptedException interruptedException) {interruptedException.printStackTrace();
                    }
                }
            }
        }.start();

        Thread.sleep(1000);
        e=null;
        System.out.println("element is null");
        System.gc();
        Thread.sleep(1000);


    }
    
    /*
    element is null
[GC (System.gc()) [PSYoungGen: 3083K->567K(29696K)] 3083K->567K(98304K), 0.0014892 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
[Full GC (System.gc()) [PSYoungGen: 567K->0K(29696K)] [ParOldGen: 0K->456K(68608K)] 567K->456K(98304K), [Metaspace: 2955K->2955K(1056768K)], 0.0046349 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
1111111
    */

原本茶队升级曾经够快乐了,起初 TA 打李逵,带来了 3 场精彩对决,看的热血沸腾的,加油茶队

本文由 mdnice 多平台公布

正文完
 0