java提供了4中引用类型,在垃圾回收的时候,都有本身的各自特色。java
为何要区分这么多引用呢,其实这和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()); } }
结果:
jvm
* 若是一个对象只是被弱引用引用者,那么只要发生GC,无论内存空间是否足够,都会回收该对象。ide
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回收的时候就忽略了这个引用,把对象当成垃圾收回了。spa
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。code
Map<String,SoftReference<Bigmap>> imageCache=new HashMap<String,SoftReference<Bitmap>>();