强引用,软引用,弱引用与虚引用

强引用:(StrongReference)

强引用指普通的对象引用

例如:

StringBuffer str = new StringBuffer("hello world");

局部变量str会被放到栈里,而StringBuffer实例对象会被放在堆内,局部变量str指向堆内的StringBuffer对象,通过str可以操作该对象,那么str就是StringBuffer的强引用

强引用,软引用,弱引用与虚引用_第1张图片

 

StringBuffer str1 = str;

当发生了这条语句,则

强引用,软引用,弱引用与虚引用_第2张图片

 

 

 此时这两个引用都是强引用

 

强引用具备如下特点:

  1、通过强引用可以直接访问目标对象

  2、强引用所指向的对象在任何时候都不会被系统回收,虚拟机宁愿抛出OOM(内存溢出)异常,也不会回收强引用所指向的对象

  3、强引用可能导致内存泄漏(站着空间不释放,积累的多了内存泄漏会导致内存溢出)

jvm也不会靠随意回收具有强引用的对象来解决内存不足的问题。如果不使用时,要通过如下方式来弱化引用,如下: o=null; // 帮助垃圾收集器回收此对象 显式地设置o为null,或超出对象的生命周期范围,则gc认为该对象不存在引用,这时就可以回收这个对象。具体什么时候收集这要取决于gc的算法。 举例: public void test(){ Object o=new Object(); } 在一个方法的内部有一个强引用,这个引用保存在栈中,而真正的引用内容(Object)保存在堆中。当这个方法运行完成后就会退出方法栈,则引用内容的引用不存在,这个Object会被回收。但是如果这个o是全局的变量时,就需要在不用这个对象时赋值为null,因为强引用不会被垃圾回收。

软引用:(SoftReference)

软引用描述一些还有用但非必需的对象,用java.lang.ref.SoftReference类表示,对于软引用关联的对象GC未必会一定会收,只有当内存资源紧张时,软引用对象才会被回收,所以软引用对象不会引起内存溢出(OOM)

复制代码
 1 import java.lang.ref.SoftReference;
 2 
 3 //软引用问题
 4 public class SoftRef {
 5     public static class User{
 6         public int id;
 7         public String name;
 8         public User(int id,String name) {
 9             this.id = id;
10             this.name = name;
11         }
12         @Override
13         public String toString() {
14             return "User [id=" + id + ", name=" + name + "]";
15         }
16         
17         
18     }
19     
20     public static void main(String[] args) {
21         User u = new User(1,"吉米");
22         //从强引用中获取软引用
23         SoftReference sr = new SoftReference(u);
24         //将强引用去除
25         u = null;
26         // get方法返回此引用对象的指示对象。用来获取与软引用关联的对象的引用
27         System.out.println(sr.get());
28         System.out.println("After GC");
29         System.gc();
30         System.out.println(sr.get());
31         
32         
33         //这样测试出来,软引用可能不会被gc回收,此时需要模拟一下内存很紧张的状态
34         byte b[] = new byte[1024*925*77];
35         System.gc();
36         System.out.println(sr.get());
37         
38     }
39 }
复制代码
输出:在-Xmx10m下输出
User [id=1, name=吉米] //第一次从软引用中获取数据 After GC User [id=1, name=吉米] //GC没有清除软引用 null //由于内存紧张,软引用被GC清理

此外,软引用还可以附带一个引用队列,当对象可达性发生改时(由可达变为不可达,被回收),此时软引用进入队列,通过这个引用队列,可以跟踪对象的回收情况 

弱引用:(WeakReference)

弱引用是比软引用还弱的引用,在系统进行GC 时,只要发现弱引用,不管系统的堆空间是用了一点还是用了一大半,都会回收弱引用的对象。但是通常GC线程的优先级较低,因此不能立即发现持有弱引用的对象,在这种情况下弱引用对象可以存在较长的时间,一旦弱引用对象被回收,弱引用对象会加到一个注册的引用队列中去

 

 强引用,软引用,弱引用与虚引用_第3张图片

 

 

 弱引用代码:

复制代码
 1 import java.lang.ref.WeakReference;
 2 
 3 //弱引用
 4 public class WeakRef {
 5     public static class User{
 6         public int id;
 7         public String name;
 8         public User(int id, String name) {
 9             this.id = id;
10             this.name = name;
11         }
12         @Override
13         public String toString() {
14             return "[id=" + id + ", name=" + name + "]";
15         }
16         
17     }
18     
19     public static void main(String[] args) {
20         User u = new User(1,"geym");
21         //创建软引用对象
22         WeakReference wr = new WeakReference(u);
23         System.out.println(wr.get());
24         System.gc();
25         System.out.println("After GC:");
26         System.out.println(wr.get());
27     }
28 }
复制代码

输出:

[id=1, name=geym]
After GC:
null

根据软引用和弱引用的特性,非常适合保存一些可有可无的缓存,如果这么做,当系统内存空间不足时,会及时回收他们,不会导致内存溢出,当系统内存资源充足时,这些还存有可以存在相当长的时间,提升系统速度。

 

虚引用:(PhantomReference)(对象回收和跟踪)

虚引用是所有引用中最弱的一个持有一个虚引用的对象,和没有引用一样,随时都有可能会被垃圾回收器回收,当用虚引用的get方法去尝试获得强引用对象时总是会失败,并且他必须和引用队列一起使用,用于跟踪垃圾回收过程,当垃圾回收器回收一个持有虚引用的对象时,在回收对象后,将这个虚引用对象加入到引用队列中,用来通知应用程序垃圾的回收情况。

虚引用代码:

复制代码
 1 import java.lang.ref.PhantomReference;
 2 import java.lang.ref.ReferenceQueue;
 3 
 4 public class PlantomRef {
 5     public static class User{
 6         public int id;
 7         public String name;
 8         public User(int id,String name){
 9             this.id = id;
10             this.name = name;
11         }
12         @Override
13         public String toString() {
14             return "User [id=" + id + ", name=" + name + "]";
15         }
16         
17     }
18     
19     public static void main(String[] args) {
20         User u = new User(1,"吉米");
21         ReferenceQueue queue = new ReferenceQueue();
22         PhantomReference pr = new PhantomReference(u,queue);
23         System.out.println(pr.get());
24         
25     }
26     
27     
28     
29 }
复制代码

输出为null

由于虚引用可以跟踪对象的回收时间,所以可以将一些资源的释放操作放置在虚引用中执行和记录

 

引用类型 被垃圾回收时间 用途 生存时间
强引用  从来不会 对象的一般状态 JVM停止运行时终止
软引用  当内存不足时 对象缓存 内存不足时终止
弱引用 正常垃圾回收时 对象缓存 垃圾回收后终止
虚引用 正常垃圾回收时 跟踪对象的垃圾回收 垃圾回收后终止

你可能感兴趣的:(强引用,软引用,弱引用与虚引用)