JVM 四种引用类型
特别说明
当前文章内容迁移中,如有问题,请提交 issues 谢谢~~
本文实践代码可以参阅 CodeCombat 的 JVM。
1. 强引用
强引用是程序中一般使用的引用类型,强引用的对象是可触及的,不会被回收。相对的,弱引用,软引用,虚引用的对象是可触及的,在一定情况下,是可以被回收的。
StringBuffer str = new StringBuffer("Hello World");
以上代码中,局部变量 str 将被分配在栈上,而对象 StringBuffer 实例对象将被分配在堆上。局部变量 str 指向 StringBuffer 实例所在的堆空间,通过 str 可以操作该实例,那么 str 就是 StringBuffer 实例的强引用。
如果此时再进行
StringBuffer str1 = str;
那么 str 所指向的对象也将被 str1 所指向,同时在局部变量表上会分配空间存放 str1 变量。此时,StringBuffer 实例就有两个引用。对引用进行 “==” 操作时,表示比较对象所指向的堆空间是否相同,不表示量操作数所指向的对象是否想等。
特点:
- 强引用可以直接访问目标对象
- 强引用所指向的对象在任何时候都不会被系统回收,虚拟机宁愿抛出 OOM 异常,也不会回收强引用所指向的对象。
- 强引用可能导致内存泄露。
2. 软引用
如果一个对象只具有软引用,在内存足够的情况下,垃圾回收区不会回收它,如果内存空间不足,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内敏感的告诉缓存。
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,JVM 就会把这个软引用加入到与之关联的引用队列中。
3. 弱引用
弱引用与软引用的区别:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描所管辖的内存区域时,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
弱引用对象可以和一个引用队列一起使用,如果弱引用所引用的对象被垃圾回收,JVM 就会把这个弱引用加入到与之关联的引用队列中。
4. 虚引用
如果一个对象仅持有虚引用,那么它和没有任何引用一样,在任何时候都可能被垃圾回收。虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与弱引用和软引用的区别在于:虚引用必须和引用队列一起使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象后,将这个虚引用加入引用队列,以通知应用程序对象的回收情况。
注意
软引用和弱引用都适合用来保存那些可有可无的缓存数据。如果这么做,当系统内存不足时,这些缓存就会被回收,不会导致内存溢出。而当内存资源充足时,这些缓存数据有可以存在相当长的时间,从而起到加速系统的作用。