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

Posted 小毛喵喵

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了强引用,软引用,弱引用与虚引用相关的知识,希望对你有一定的参考价值。

强引用:(StrongReference)

强引用指普通的对象引用

例如:

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

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

 

StringBuffer str1 = str;

当发生了这条语句,则

 

 

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

 

强引用具备如下特点:

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

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

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

 

软引用:(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<User> sr = new SoftReference<User>(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线程的优先级较低,因此不能立即发现持有弱引用的对象,在这种情况下弱引用对象可以存在较长的时间,一旦弱引用对象被回收,弱引用对象会加到一个注册的引用队列中去

 

 

 

 

 弱引用代码:

 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<User> wr = new WeakReference<User>(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<? super User> queue = new ReferenceQueue<User>();
22         PhantomReference<User> pr = new PhantomReference<User>(u,queue);
23         System.out.println(pr.get());
24         
25     }
26     
27     
28     
29 }

输出为null

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

 

以上是关于强引用,软引用,弱引用与虚引用的主要内容,如果未能解决你的问题,请参考以下文章

Java:强引用软引用弱引用与虚引用

强引用弱引用软引用虚引用

java强引用,软引用,弱引用和虚引用

Java四种引用 强引用,软引用,弱引用,虚引用(转)

Java四大引用详解:强引用软引用弱引用虚引用

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