java提供了4中引用类型,在垃圾回收的时候,都有自己的各自特点。

为什么要区分这么多引用呢,其实这和Java的GC有密切关系。
  public static void main(String[] args) {
        Object obj=new Object();//这样定义就是一个强引用
        Object obj2=obj;//也是一个强引用
        obj=null;
        System.gc();
        //不会被垃圾回收
        System.out.println(obj2);
    }
 /**
     * jvm配置配置小的内存,故意产生大的对象,导致OOM,
     * 验证软引用在内存足够的前后是否被回收。
     * 参数:-Xms:5M -Xmx:5M
     * @param args
     */
    public static void main(String[] args) {
        Object obj=new Object();//这样定义就是一个强引用
        //软引用需要使用java.lang.SoftReference来实现
        //现在sf就是一个软引用
        SoftReference sf=new SoftReference(obj);
        obj=null;
        System.out.println("内存足够软引用引用的对象"+sf.get());
        try {
            final byte[] bytes = new byte[8 * 1024 * 1024];
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            System.out.println("内存不够:软引用引用的对象:"+sf.get());
        }
    }
结果:

* 如果一个对象只是被弱引用引用者,那么只要发生GC,不管内存空间是否足够,都会回收该对象。
 public static void main(String[] args) {
        Object obj=new Object();
        WeakReference wrf=new WeakReference(obj);
        obj=null;
        System.out.println("未发生GC之前"+wrf.get());
        System.gc();
        System.out.println("内存充足,发生GC之后"+wrf.get());
    }
结果:
未发生GC之前java.lang.Object@2d363fb3
内存充足,发生GC之后null
WeakHashMap的键是“弱键”,也就是键的引用是一个弱引用。
 public static void main(String[] args) {
        WeakHashMap<String,Integer> map=new WeakHashMap<>();
        String key = new String("wekHashMap");
        map.put(key,1);
        key=null;
        System.gc();
        System.out.println(map);
    }
结果:map为空了。
理论上我们只是把引用变量key变成null了,"wekHashMap"字符串应该被Map中key引用啊,不应该被GC回收啊,
但是因为key是弱引用,GC回收的时候就忽略了这个引用,把对象当成垃圾收回了。
class User{
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("我要被GC干了!");
    }
}
 public static void main(String[] args) throws  Exception {
        User user=new User();
        ReferenceQueue<User> queue=new ReferenceQueue();
        PhantomReference prf=new PhantomReference(user,queue);
        //启动一个线程监控引用队列的变化
        new Thread(()->{
            for(;;){
                final Reference<? extends User> u = queue.poll();
                if (u!=null){
                    System.out.println("有对象被加入到了引用队列了!"+u);
                }
            }
        }).start();
        user=null;
        //GC之前引用队列为空
        System.out.println("GC之前"+queue.poll());
        
        System.gc();
        Thread.sleep(100);
        //GC之后引用队列才将对象放入
        System.out.println("第一次GC之后"+queue.poll());
        System.gc();
        Thread.sleep(100);
        System.out.println("第二次GC之后"+queue.poll());
    }
结果:
GC之前null
我要被GC干了!
第一次GC之后null
有对象被加入到了引用队列了!java.lang.ref.PhantomReference@549763fd
第二次GC之后java.lang.ref.PhantomReference@5aaa6d82 
假如有一个应用需要读取大量的本地图片
每次读取图片都从硬盘读取会影响性能。
一次全部加载到内存中,又可能造成内存溢出。
此时,可以使用软引用解决问题;
使用一个HashMap保存图片的路径和响应图片对象关联的软引用之间的映射关系,
内存不足时,jvm会自动回收这些缓存图片对象所占用的空间,可以避免OOM。
Map<String,SoftReference<Bigmap>> imageCache=new HashMap<String,SoftReference<Bitmap>>();原文:https://www.cnblogs.com/wangsen/p/11206956.html