zoukankan      html  css  js  c++  java
  • 虚引用

    虚引用在垃圾回收时候,抢救不了了。对象回收的时候直接回收,如果用ReferenceQueue,那么在回收时候通过这个队列,可以人为做些处理。软引用弱引用先置位referentnull回收堆内存,然后把虚引用对象加入队列,最后在队列里面回收虚引用对象。

    虚引用必须要和ReferenceQueue结合使用软引用弱引用可以不和ReferenceQueue结合使用。

    强引用 : 就是普通的引用. 内存不足抛 Out of Memory 异常

    软引用(SoftReferenve) : 内存充足的情况下不会被回收,内存不充足的情况下才会被回收。能够很好地规避OOM异常。

    弱引用(WeakReference) : 当垃圾回收机制运行时, 弱引用引用的对象就会被回收掉.

    // 新建一个引用队列

    ReferenceQueue<TestObject> referenceQueue = new ReferenceQueue<>();

    // 建立一个TestObject的弱引用

    SoftReference<TestObject> reference = new SoftReference<>(new TestObject(), referenceQueue)

    引用和软引用在创建的时候都可以传进去一个引用队列(当然也可以不使用引用队列), 当弱引用和软引用引用的对象需要进行回收的时候, JVM都是先将其referent字段设置成null,之后将软引用或弱引用对象本身,加入到关联的引用队列中。也就是说JVM先回收堆对象内存,然后才将软引用或弱引用本身加入到引用队列。

    // 创建一个引用队列

    ReferenceQueue<TestObject> referenceQueue = new ReferenceQueue<>();

    PhantomReference reference = new PhantomReference<>(new TestObject(), referenceQueue);

    而虚引用(PhantomReference) 不同, 必须和引用队列 ReferenceQueue)联合使用, GC启动时, 则将引用对象传到它的引用队列中去. 但是不会将虚引用的referent字段设置成null, 就是不会释放虚引用指向的TestObject堆对象内存空间

    如果虚引用引用的对象重写了finalize方法, 在虚引用对象传到它的引用队列之前还会调用对象的finalize方法, 但是调用之后内存不会回收.
    你可以通过手动调用PhantomReference.clear()方法来释放虚引用指向的的堆对象内存空间

    虚引用的存在更倾向于实现程序员对内存回收的细粒度性控制, 当虚引用确定会被回收之后, 会向应用程序发送通知, 此时程序员进行对内存清理的细微操作.

     

    public static void main(String[] args) {
            Object obj = new Object();
            ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>();
            WeakReference<Object> weakRef = new WeakReference<Object>(obj, refQueue);
            System.out.println(weakRef.get());//返回weakRef里面的obj
            System.out.println(refQueue.poll());//队列灭有元素
            obj = null;//只有weakRef 指向new Object()内存,不置位null,gc时候不会将weakRef 的eferent被置位了null,也不会将weakRef加入refQueue队列
            System.gc();
            System.gc();
            System.gc();
            System.gc();//System.gc()是告诉JVM这是一个执行GC的好时机,但具体执不执行由JVM决定,
            System.out.println(weakRef.get());//referent被置位了null
            System.out.println(refQueue.poll());//队列里面有一个元素weakRef但是weakRef的referent被置位了null
        }

     

     public class Test0009 {
        public static void main(String[] args) throws InterruptedException {
            Object obj = new Object();
            ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>();
            PhantomReference<Object> phanRef = new PhantomReference<Object>(obj, refQueue);
            System.out.println(phanRef.get());//null,phanRef里面有元素但是一直返回null,因为PhantomReference重写了Reference的get方法,写死了返回null
            System.out.println(refQueue.poll());//队列为空,
            obj = null;//不置位null,phanRef里面有元素,队列为空。
            System.gc();
            System.gc();
            System.gc();
            System.out.println(phanRef.get());//phanRef里面仍然有元素,referent并没有像弱引用软引用那样置位空
            System.out.println(refQueue.poll());//队列有元素,
        }
    }
    class Registry {
        private Set registeredObjects = new HashSet();
     
        public void register(Object object) {
            registeredObjects.add( object );
        }
    }
    所有我添加进 registeredObjects 中的object永远不会被GC回收,因为这里有个强引用保存在registeredObjects里,
    object 内存对象被2个强引用关联。另一方面如果我把代码改为如下:
    class Registry {
         private Set registeredObjects = new HashSet();
     
         public void register(Object object) {
             registeredObjects.add( new WeakReference(object) );
         }
     }
    现在如果GC想要回收registeredObjects中的object,object 内存对象被1个强引用1个弱引用关联,便能够实现了,
    同样在使用HashMap如果想实现如上的效果,一种更好的实现是使用WeakHashMap

    强引用:一直不回收

    软引用:内存不足回收

    弱引用:gc就回收

    虚引用:  “虚引用”顾名思义,就是形同虚设,一个对象仅持有虚引用,那么它就和没有任何引用一样。虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用必须和引用队列 ReferenceQueue)联合使用。

    当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。

    虚引用里面的对象没有强引用时候,开始回收,加入到队列去,并不会置referentnull

    软引用弱引用里面的对象没有强引用时候,开始回收,加入到队列去,置referentnull

    public class MyDate extends Date { 
    
        /** Creates a new instance of MyDate */
        public MyDate() {
        }
        // 覆盖finalize()方法,finalize()函数是在JVM回收内存时执行的,
        protected void finalize() throws Throwable {
            super.finalize();
            System.out.println("obj [Date: " + this.getTime() + "] is gc");
        }   
    
        public String toString() {
            return "Date: " + this.getTime();
        }
    }

    虚引用也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。一个仅仅持有虚引用的对象,和没有引用几乎是一样的,随时都有可能被垃圾回收器回收。当试图通过虚引用的get()方法取得强引用时,总是会失败。并且,虚引用必须和引用队列一起使用,它的作用在于跟踪垃圾回收过程。

    当你的虚引用所引用的对象已经执行完finalize函数的时候,就会把对象加到queue里面。

    广义的堆外内

    -Xmx的值是新生代和老生代的和的最大值,-XX:MaxPermSize来指定持久代的最大值Java堆的最大值其实是-Xmx和-XX:MaxPermSize的总和

    那么剩下的都可以认为是堆外内存(广义的)了,这些包括了jvm本身在运行过程中分配的内存,codecache,jni里分配的内存,DirectByteBuffer分配的内存等等

    狭义的堆外内存

    这个主要是指java.nio.DirectByteBuffer在创建的时候分配内存/

     

  • 相关阅读:
    unity IOC 的使用
    Senparc之OAuth原理
    改进的日志记录类
    发一个 Nuget打包发布小工具
    贴一个微信小程序跳一跳辅助
    调用API让声卡发出声音
    控制台彩色输出
    C#调用cmd实现自我删除
    一个适合新手的简易计算器
    简单Console进度条
  • 原文地址:https://www.cnblogs.com/yaowen/p/10975241.html
Copyright © 2011-2022 走看看