java中的各种引用介绍

本文详细解析了Java中软引用和弱引用的区别及其应用场景,包括如何利用软引用结合HashMap构建有效的缓存机制来避免OOM问题,同时介绍了弱引用在WeakHashMap中的运用。

主要讲解软引用和弱引用的概念以及引用队列的用法,最后介绍了weakhashmap,关于自定义使用软引用结合hashmap构建缓存,可以看参考文章,以后有机会也会专门写一篇介绍。

java中各种引用存活周期

强引用>软引用>弱引用>虚引用。

  • StrongReference-jvm内存不足时也不会回收,直至OOM。
  • SoftReference-jvm进行垃圾回收,内存不足,避免OOM会对软引用的对象进行回收。
  • WeakReference-JVM进行垃圾回收时会回收弱引用,无论内存是否紧张。
  • PhantomReference-任何时候都可能被回收。

软引用和弱引用概念区分

Soft reference objects, which are cleared at the discretion of the garbage collector in response to memory demand. Soft references are most often used to implement memory-sensitive caches.
All soft references to softly-reachable objects are guaranteed to have been cleared before the virtual machine throws an OutOfMemoryError.

对于软引用因为内存需求会被释放。抛出OOM之前确定所有软引用被释放。

Weak reference objects, which do not prevent their referents from being made finalizable, finalized, and then reclaimed. Weak references are most often used to implement canonicalizing mappings.

对于弱引用gc的时候一定会被释放。

软引用的使用

(使用系统去判断释放时机,而非缓存算法。)

软引用示例

    public class SoftReferenceTest
    {

        /**
         * @param args
         */
        public static void main(String[] args)
        {
            //软引用的利用,首先强引用构造软引用,然后强引用放空,使用软引用,软引用为空时重新初始化对象,一种缓存机制
            A a = new A();
            SoftReference<A> sa = new SoftReference<A>(a);
            a = null;

            System.out.println("use a --->");

            //具体使用a对象的时候利用如下代码
            if(sa != null)
            {
                a = (A)sa.get();
            }
            else
            {
                a = new A();
                sa = new SoftReference<A>(a);
            }

            //gc对软引用的影响
            System.out.println("gc effect for softreference");
            System.out.println(sa.get());
            System.gc();
            System.out.println(sa.get()); //由于这里的场景内存不紧张,所以不会回收

            //gc对弱引用的影响
            A b = new A();
            WeakReference<A> sb = new WeakReference<SoftReferenceTest.A>(b);
            b = null;
            System.out.println("gc effect for weakreference");
            System.out.println(sb.get());
            System.gc();
            System.out.println(sb.get());//得到的是null,上一句gc触发垃圾回收,弱引用被释放,调用finalize

        }

        public static class A
        {
            public A()
            {

            }

            @Override
            protected void finalize() throws Throwable
            {
                // TODO Auto-generated method stub
                super.finalize();
                System.out.println("finalize of A" + this.toString());
            }
        }
    }

/*
use a --->
gc effect for softreference
com.bityan.learning.SoftReferenceTest$A@2ce1b3b3
com.bityan.learning.SoftReferenceTest$A@2ce1b3b3
gc effect for weakreference
com.bityan.learning.SoftReferenceTest$A@15128ee5
null
finalize of Acom.bityan.learning.SoftReferenceTest$A@15128ee5
*/

注意,代码调用gc,对于system.gc()使得gc过程在此后一个不固定时间触发,不一定是立即调用。同样jvm不保证对象的finalize一定被调用,但是finalize方法只能被调用一次。

软引用和引用队列

引用队列用于判断软引用是否失效以及释放软引用本身这个引用(强引用)。
当软可及对象被回收之后,虽然这个SoftReference对象的get()方法返回null,但这个SoftReference对象已经不再具有存在的价值,需要一个适当的清除机制,避免大量SoftReference对象带来的内存泄漏。如果在创建SoftReference对象的时候,使用了一个ReferenceQueue对象作为参数提供给SoftReference的构造方法,那么软引用被gc处理后,会将软引用本身这个引用加入到referenceQueue中,通过队列的poll方法可以查到对应对象被释放掉的软引用。

构造软引用时引入引用队列:

ReferenceQueue queue = new ReferenceQueue();
SoftReference ref=new SoftReference(aMyObject, queue);

通过引用队列去看是否有被释放的引用对象,此引用已经无效。

SoftReference ref = null;
while ((ref = q.poll()) != null) {
// 清除ref
}

WeakHashMap

一种hashmap,如果key不被引用,则此键值对被移除。

    import java.util.Map;
    import java.util.WeakHashMap;

    public class WeakHashMapDemo
    {

        private static Map<String, String> map;

        public static void main(String args[])
        {
            map = new WeakHashMap<String, String>();

            map.put(new String("Maine"), "Augusta");

            Runnable runner = new Runnable()
            {
                public void run()
                {
                    while (map.containsKey("Maine"))
                    {
                        try
                        {
                            Thread.sleep(500);
                        } catch (InterruptedException ignored)
                        {
                        }
                        System.out.println("Thread waiting");
                        System.gc();
                    }
                }
            };
            Thread t = new Thread(runner);
            t.start();
            System.out.println("Main waiting");
            try
            {
                t.join();
            } catch (InterruptedException ignored)
            {
            }
        }
    }
/**
 * output
 * Main waiting
 * Thread waiting
 */

map.put(new String(“Maine”), “Augusta”);
使用匿名参数,对于作为key的string没有强引用指向它,根据weakhashmap的规则,gc的时候这个key对应的键值对被移除。
weakhashmap充分利用了weakreference的特性,使用弱引用来做键值。
关于weakhashmap的一段介绍

WeakHashMap is an implementation of the Map interface that stores only weak references to its keys. Storing only weak references allows a key-value pair to be garbage-collected when its key is no longer referenced outside of the WeakHashMap.

关于weakReference的一段介绍

Weak Reference − If the only references to an object are weak references, the garbage collector can reclaim the object’s memory at any time.it doesn’t have to wait until the system runs out of memory. Usually, it will be freed the next time the garbage collector runs.

参考文档

  1. 软引用和引用队列
    http://alinazh.blog.51cto.com/5459270/1276173

  2. 善用软引用构建缓存有效避免OOM
    http://www.cnblogs.com/dolphin0520/p/3784171.html

Java中的引用类型有强引用软引用弱引用和虚引用,它们在内存管理中发挥着不同的作用,以下是对这四种引用类型的详细介绍: - **强引用**:是最常见的引用类型,适用于日常开发中需要持续使用的对象。只要强引用存在,垃圾回收器就不会回收被引用的对象[^1][^2]。 ```java Object strongRef = new Object(); // 强引用 ``` - **软引用**:适合用于缓存管理,在内存充足时,软引用的对象不会被回收;但在内存紧张时,垃圾回收器会回收这些对象。软引用可以关联引用队列,用于跟踪引用对象的状态变化[^2][^3]。 ```java import java.lang.ref.SoftReference; import java.lang.ref.ReferenceQueue; // 创建引用队列 ReferenceQueue<Object> queue = new ReferenceQueue<>(); // 创建软引用 SoftReference<Object> softRef = new SoftReference<>(new Object(), queue); ``` - **弱引用**:是更弱的引用类型,不管内存中是否有空间,只要遇到垃圾回收器,弱引用的对象就会被回收,常用于避免内存泄漏,也可关联引用队列[^2][^3][^4]。 ```java import java.lang.ref.WeakReference; import java.lang.ref.ReferenceQueue; // 创建引用队列 ReferenceQueue<Object> queue = new ReferenceQueue<>(); // 创建弱引用 WeakReference<Object> weakRef = new WeakReference<>(new Object(), queue); ``` - **虚引用**:主要用于监控对象的回收,以便在对象销毁后执行特定的清理操作。虚引用必须关联引用队列,且```get()```方法永远返回```null```,其对象最优先被回收,典型的回收时机不确定[^2][^3]。 ```java import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; // 创建引用队列 ReferenceQueue<Object> queue = new ReferenceQueue<>(); // 创建虚引用 PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), queue); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值