zoukankan      html  css  js  c++  java
  • 强引用,软引用,弱引用与虚引用

    强引用:(StrongReference)

    强引用指普通的对象引用

    例如:

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

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

    StringBuffer str1 = str;

    当发生了这条语句,则

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

    强引用具备如下特点:

      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<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

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

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

  • 相关阅读:
    在为知笔记中使用JQuery
    解决Wireshark安装Npcap组件失败
    SSL/TLS抓包出现提示Ignored Unknown Record
    Metasploit中aggregator插件无法使用
    Metasploit运行环境内存不要低于2GB
    如何查看抓包文件所使用的捕获过滤器
    Nvidia的CUDA库现在恢复使用了
    Metasploit远程调用Nessus出错
    Nessus更新到8.3.0
    Kali Linux安装字典StarDict
  • 原文地址:https://www.cnblogs.com/nyhhd/p/12636224.html
Copyright © 2011-2022 走看看