Java核心技术之强引用、软引用、弱引用、幻象引用

Java一共有四种不同的引用类型,主要体现的是对象不同的可达性状态和对垃圾收集的影响。

1. 强引用

所谓强引用就是我们最常见的普通对象引用,只要还有强对象引用指向一个对象,就能表明该对象还活着,垃圾收集器不会碰这种对象。对于一个普通的对象,如果没有其他引用关系,只要超过了引用的作用域或者显示的将相应(强)引用赋值为null,就是可以被垃圾收集的了,当然具体回收时机还是要看垃圾回收策略。

 	public static void main(String[] args) throws InterruptedException {
        //user1会超过作用域
        {
            User user1=new User("u1");
        }
        //user2显示的将强引用赋null
        User user2=new User("u2");
        user2=null;
 
        User user3=new User("u3");
 
        System.gc();
        Thread.sleep(5000);
    }

2. 软引用(SoftRefrence)

软引用是一种相对弱化一点的强引用,可以让对象豁免一些垃圾收集,只有当JVM认为内存不够时,才会对该引用指向的对象进行垃圾回收。JVM会确保在抛出OOM之前进行软引用对象的回收。软引用通常用来实现内存敏感的缓存。

	public static void main(String[] args) throws InterruptedException {
        User user=new User("张三");
        SoftReference<User> soft=new SoftReference<User>(user);
        user=null;
        System.gc();
        /*
         *  soft.get()  @return  The object to which this reference refers,
         *  or null if this reference object has been cleared
         */
        if(soft.get()==null) {
            System.out.println("软引用对象已经被清理,此时没有引用指向User对象");
        }else {
            System.out.println("name:"+soft.get().getName());
        }
    }

3. 弱引用(WeakRefrence)

弱引用不会使对象豁免垃圾收集,仅仅是提供一种访问在弱引用状态下对象的途径。这就可以用来构建一种没有特定约束的关系,比如,维护一种非强制性的映射关系,如果试图获取时对象还在,就使用它,否则重新实例化。

  		//弱引用
        User user=new User("张三");
        WeakReference<User> weak=new WeakReference<User>(user);
        user=null;
       //System.gc();
        if(weak.get()==null) {
            System.out.println("弱引用对象已经被清理,此时没有引用指向User对象");
        }else {
            System.out.println("name:"+weak.get().getName());
        }

4. 幻象引用(PhantomReference)

幻象引用主要用来跟踪对象被垃圾回收器回收的活动。幻象引用与软引用和弱引用的一个区别在于:幻象引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有幻象引用,就会在回收对象的内存之前,把这个幻象引用加入到与之 关联的引用队列中。

        User user=new User("张三",12);
		ReferenceQueue queue=new ReferenceQueue();
		PhantomReference<User> phantomRef=new PhantomReference<User>(user,queue);
		user=null;

显示的影响软引用垃圾收集:
软引用通常会在最后一次引用后,还能保持一段时间,默认值是根据堆剩余空间计算的(以M bytes为单位)。从Java1.3.1开始,提供了-XX:SoftRefLRUPolicyMSPerMB参数,我们可以以毫秒(milliseconds)为单位设置。比如,下面这个示例就是设置为3秒。

-XX:SoftRefLRUPolicyMSPerMB=3000

这个剩余空间,其实会受到不同JVM模式的影响,对于Client模式,比如通常的Windows32 bit JDK,剩余空间是计算当前堆里的空闲的大小,所以更加倾向于回收;而对于server模式JVM,则是根据-Xmx指定的最大值来计算。

诊断JVM引用情况(Java8中):

-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintReferenceGC

Reachability fence,在Java9中使用reachabilityFence达到强引用的效果:

class Resource {
 private static ExternalResource[] externalResourceArray = ...
 int myIndex; Resource(...) {
     myIndex = ...
     externalResourceArray[myIndex] = ...;
     ...
 }
 protected void finalize() {
     externalResourceArray[myIndex] = null;
     ...
 }
 public void action() {
 try {
     // 需要被保护的代码
     int i = myIndex;
     Resource.update(externalResourceArray[i]);
 } finally {
     // 调用 reachbilityFence,明确保障对象 strongly reachable
     Reference.reachabilityFence(this);
 }
 }
 private static void update(ExternalResource ext) {
    ext.status = ...;
 }
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值