1.强引用
当内存不足,JVM开始垃圾回收,对于强引用的对象,就算是出现了OOM也不会对该对象进行回收,死都不收。
强引用是我们最常见的普遍对象引用,只要还有强引用指向一个对象,就能表明对象还活着,垃圾收集器不会碰这种对象。在JAVA最常见的就是强引用,把一个对象赋给一个引用变量就是一个强引用。当一个对象被强引用变量引用时,它处于可达状态,它是不可能被垃圾回收机制回收的,即使该对象以后永远都不会被用到JVM也不会回收,因此强引用时造成Java内存泄漏的主要原因之一。
对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显式地将相应(强)引用复制为null,一版认为就是可以背垃圾收集了。
public class StrongReferenceDemo { public static void main(String []args) { Object obj1 = new Object(); //这样定义默认是强引用 Object obj2 = obj1; obj1 = null; System.gc(); System.out.println(obj1); System.out.println(obj2); } }
2.软引用
软引用是一种相对强引用弱化了一些的引用,需要用java.lang.ref.SoftReference类来实现,可以让对象豁免一些垃圾收集,对于只有软引用的对象来说,
当系统内存充足时它不会被回收,当系统内存不足时它会被回收。
软引用通常用在对内存敏感的程序中,比如高速缓存就有用到软引用,内存够用的时候就保留,不够用就回收!
-Xms5m -Xmx5m -XX:+PrintGCDetails //设置参数
public class SoftReferenceDemo { public static void main(String []args) { Object o1 = new Object(); SoftReference<Object> softReference = new SoftReference<Object>(o1); System.out.println(o1); System.out.println(softReference.get()); o1 = null; System.gc(); try { byte[] bytes = new byte[30*1024*1024]; } finally { System.out.println(o1); System.out.println(softReference.get()); } } }
3.弱引用
弱引用需要用java.lang.ref.WeakReference类来实现,它比软引用的生存区更短。
对于只有弱引用的对象来说,只要垃圾回收机制一运行,不管JVM的内存空间是否足够,都会回收该对象占用的内存。
public class WeakReferenceDemo { public static void main(String[] args) { Object o1 = new Object(); WeakReference<Object> weakReference = new WeakReference<Object>(o1); System.out.println(o1); System.out.println(weakReference.get()); o1 = null; System.gc(); System.out.println("----------------------------"); System.out.println(o1); System.out.println(weakReference.get()); } }
public class HashMapDemo { public static void main(String []args) { myHashMap(); } private static void myHashMap() { HashMap<Integer,String> map = new HashMap<>(); Integer key = new Integer(1); String value = "hashMap"; map.put(key,value); System.out.println(map); key = null; System.out.println(map); System.gc(); System.out.println(map); } }
public class WeakHashMapDemo { public static void main(String []args) { myWeakHashMap(); } private static void myWeakHashMap() { WeakHashMap<Integer,String> map = new WeakHashMap<>(); Integer key = new Integer(2); String value = "weakHashMap"; map.put(key,value); System.out.println(map); key = null; System.out.println(map); System.gc(); System.out.println(map); } }
4.虚引用
虚引用需要java.lang.ref.PhantomReference类来实现。
顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。
如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时间都可能被垃圾回收
器回收,它不能单点使用也不能通过它访问对象,虚引用必须和引用队列(ReferenceQueue)联合使用。
虚引用的主要作用是跟踪对象被垃圾回收的状态,仅仅是提供了一种确保对象被finalize以后,做某些事情的机制。PhantomReference的get方法总是返回null,因此无法访问对应的引用对象,其意义在于说明一个对象已经进入了finalization阶段,可以被gc回收,用来实现比finalization机制更灵活的回收操作。
换句话说,设置虚引用关联的唯一目的,就是在这个对象被收集器回收的时候收到一个系统通知或者后续添加进一步的处理。Java技术允许使用fianlize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作
public class PhantomReferenceDemo { public static void main(String []args) throws Exception { Object o1 = new Object(); ReferenceQueue<Override> referenceQueue = new ReferenceQueue<>(); PhantomReference<Object> phantomReference = new PhantomReference(o1,referenceQueue); System.out.println(o1); System.out.println(phantomReference.get()); System.out.println(referenceQueue.poll()); System.out.println("-----------------"); o1 = null; System.gc(); Thread.sleep(500); System.out.println(o1); System.out.println(phantomReference.get()); System.out.println(referenceQueue.poll()); } }