精华内容
下载资源
问答
  • 强软弱虚引用区别

    2020-03-24 00:49:08
    1 强引用 特点:我们平常典型编码Object obj = new Object()中的obj就是强引用。通过关键字new创建的对象所关联的引用就是强引用。 当JVM内存空间不足,JVM宁愿抛出OutOfMemoryError运行时错误(OOM),使程序异常...

    1 强引用

    特点:我们平常典型编码Object obj = new Object()中的obj就是强引用。通过关键字new创建的对象所关联的引用就是强引用。 当JVM内存空间不足,JVM宁愿抛出OutOfMemoryError运行时错误(OOM),使程序异常终止,也不会靠随意回收具有强引用的“存活”对象来解决内存不足的问题。对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显式地将相应(强)引用赋值为 null,就是可以被垃圾收集的了,具体回收时机还是要看垃圾收集策略。

    2 软引用

    特点:软引用通过SoftReference类实现。 软引用的生命周期比强引用短一些。只有当 JVM 认为内存不足时,才会去试图回收软引用指向的对象:即JVM 会确保在抛出 OutOfMemoryError 之前,清理软引用指向的对象。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。后续,我们可以调用ReferenceQueue的poll()方法来检查是否有它所关心的对象被回收。如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。

    应用场景:软引用通常用来实现内存敏感的缓存。如果还有空闲内存,就可以暂时保留缓存,当内存不足时清理掉,这样就保证了使用缓存的同时,不会耗尽内存。

    3 弱引用

    弱引用通过WeakReference类实现。 弱引用的生命周期比软引用短。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。由于垃圾回收器是一个优先级很低的线程,因此不一定会很快回收弱引用的对象。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。ThreadLocalMap

    应用场景:弱应用同样可用于内存敏感的缓存。

    4 虚引用

    特点:虚引用也叫幻象引用,通过PhantomReference类来实现。无法通过虚引用访问对象的任何属性或函数。幻象引用仅仅是提供了一种确保对象被 finalize 以后,做某些事情的机制。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。
    ReferenceQueue queue = new ReferenceQueue ();
    PhantomReference pr = new PhantomReference (object, queue);
    程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取一些程序行动。

    应用场景:可用来跟踪对象被垃圾回收器回收的活动,当一个虚引用关联的对象被垃圾收集器回收之前会收到一条系统通知。

    展开全文
  • jvm之强软弱虚引用

    万次阅读 2020-07-16 19:58:56
    强软弱虚引用 在java中,除了基本数据类型的变量外,其他所有的变量都是引用类型,指向堆上各种不同的对象。 在jvm中,除了我们常用的引用外,还有软引用、弱引用、虚引用,这四种引用类型的生命周期与jvm的垃圾...

    强软弱虚引用

    在java中,除了基本数据类型的变量外,其他所有的变量都是引用类型,指向堆上各种不同的对象。

    在jvm中,除了我们常用的强引用外,还有软引用、弱引用、虚引用,这四种引用类型的生命周期与jvm的垃圾回收过程息息相关。

    那么这四种引用类型有什么区别?具体使用场景是什么?

    所有引用类型,都是抽象类java.lang.ref.Reference的子类,这个类的主要方法为get()方法:

        public T get() {
            return this.referent;
        }
    

    除了虚引用(因为get永远返回null),如果对象还没有被销毁,都可以通过get方法获取原有对象。这意味着,利用软引用和弱引用,我们可以将访问到的对象,重新指向强引用,也就是人为的改变了对象的可达性状态!

    强引用

    强引用(Strong references)就是直接new一个普通对象,表示一种比较强的引用关系,只要还有强引用对象指向一个对象,那么表示这个对象还活着,垃圾收集器宁可抛出OOM异常,也不会回收这个对象。

    例如下面的引用u就是一个强引用。

    public class StrongReferenceDemo {
        public static void main(String[] args) throws IOException {
            User u = new User();
            System.out.println(u);
            u = null;
            System.gc();
    
            System.in.read();
        }
    }
    
    public class User {
    
        @Override
        protected void finalize() throws Throwable {
            System.out.println("call User finalize() method");
        }
    }
    

    上面的User对象重写了父类Object的finalize(),在GC准备释放对象所占用的内存空间之前,它将首先调用finalize()方法。

    在Java中,由于GC的自动回收机制,因而并不能保证finalize方法会被及时地执行(垃圾对象的回收时机具有不确定性),也不能保证它们会被执行(程序由始至终都未触发垃圾回收),所以finalize不推荐使用,这里只是为了演示垃圾回收的过程。

    另外finalize()最多只会被调用一次,也就是只能利用finalize()为对象续命一次。

    软引用

    软引用用于存储一些可有可无的东西,例如缓存,当系统内存充足时,这些对象不会被回收,当系统内存不足时也是GC时才会回收这些对象,如果回收完这些对象后内存还是不足,就会抛出OOM异常。

    // vm args: -Xmx36m -XX:+PrintGCDetails
    public class SoftReferenceDemo {
        public static void main(String[] args) throws InterruptedException {
    
            SoftReference<User> softReference = new SoftReference<>(new User()); // 软引用
    
            System.out.println(softReference.get());
    
            System.gc(); 
    
            TimeUnit.SECONDS.sleep(3); // wait gc thread run
    
            System.out.println(softReference.get()); // User对象不会被回收
    
            byte[] bytes = new byte[1024 * 1024 * 10]; // 分配一个大对象使得堆空间不足,软引用对象会在OOM之前先被回收
            System.out.println(softReference.get());
    
        }
    }
    

    在上面的例子中,第一次发生gc时,User对象不会被回收,第二次发生gc时由于堆空间不足,会先回收软引用的对象,回收完了还是空间不足,最后抛出OOM异常。

    弱引用

    弱引用(WeakReference)并不能使对象豁免垃圾回收,仅仅是提供一种访问在弱引用状态下对象的途径。只要发生gc,弱引用对象就会被回收。ThreadLocal中就使用了WeakReference来避免内存泄漏。

    public class WeakReferenceDemo {
    
        public static void main(String[] args) throws InterruptedException {
    
            WeakReference<User> weakReference = new WeakReference<>(new User());
    
            System.out.println(weakReference.get());
    
            System.gc();
    
            TimeUnit.SECONDS.sleep(3); // wait gc thread run
    
            System.out.println(weakReference.get()); // null
        }
    }
    

    上面的例子只要发生gc,User对象就会被垃圾收集器回收。

    虚引用

    虚引用必须和引用队列(ReferenceQueue)联合使用。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。

    虚引用主要用来跟踪对象被垃圾回收的活动。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象之前,把这个虚引用加入到与之关联的引用队列中。程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

    // vm args: -Xms4m -XX:+PrintGC
    public class PhantomReferenceDemo {
    
        public static void main(String[] args) throws IOException, InterruptedException {
            ReferenceQueue<User> referenceQueue = new ReferenceQueue<>(); // 引用队列
            PhantomReference<User> phantomReference = new PhantomReference<>(new User(), referenceQueue); // 虚引用
    
            System.out.println(phantomReference.get()); // null
    
    
            new Thread(() -> {
                while (true) {
                    Reference<? extends User> poll = referenceQueue.poll();
                    if (poll != null) {
                        System.out.println("--- 虚引用对象被jvm回收了 ---- " + poll);
                        System.out.println("--- 回收对象 ---- " + poll.get()); // null
                    }
                }
            }).start();
    
            TimeUnit.SECONDS.sleep(1);
    
            System.gc();
    
            System.in.read();
    
        }
    
        private static class User {
    
            private int[] bytes = new int[1024 * 1024 * 5];
    
            @Override
            protected void finalize() throws Throwable {
                System.out.println("call User finalize() method");
            }
        }
    }
    

    实际上,虚引用的get()方法总是返回null。

    基于虚引用,有一个更加优雅的实现方式,那就是Cleaner,可以用来替代Object类的finalizer方法,在DirectByteBuffer中用来回收堆外内存。

    更多精彩内容关注本人公众号:架构师升级之路
    在这里插入图片描述

    展开全文
  • 关注Java后端技术栈”回复“面试”获取最新资料以前学习强软弱虚引用的时候,只是走马观花看看博客,并没有自己写代码去实践、去证明,导致每次看完后,过不了多久就忘了,后来下定决心,一定要自...

    关注Java后端技术栈

    回复“面试”获取最新资料

    以前学习强软弱虚引用的时候,只是走马观花看看博客,并没有自己写代码去实践、去证明,导致每次看完后,过不了多久就忘了,后来下定决心,一定要自己敲敲代码,这样才能让印象更加深刻,古人云:纸上得来终觉浅,绝知此事要躬行。

    Java中的四种引用

    Java中有四种引用类型:强引用、软引用、弱引用、虚引用。

    Java为什么要设计这四种引用

    Java的内存分配和内存回收,都不需要程序员负责,都是由伟大的JVM去负责,一个对象是否可以被回收,主要看是否有引用指向此对象,说的专业点,叫可达性分析。

    Java设计这四种引用的主要目的有两个:

    • 可以让程序员通过代码的方式来决定某个对象的生命周期;

    • 有利用垃圾回收。

    强引用

    强引用是最普遍的一种引用,我们写的代码,99.9999%都是强引用:

    Object o = new Object();
    

    这种就是强引用了,是不是在代码中随处可见,最亲切。

    只要某个对象有强引用与之关联,这个对象永远不会被回收,即使内存不足,JVM宁愿抛出OOM,也不会去回收。

    那么什么时候才可以被回收呢?当强引用和对象之间的关联被中断了,就可以被回收了。

    我们可以手动把关联给中断了,方法也特别简单:

    o = null;
    

    我们可以手动调用GC,看看如果强引用和对象之间的关联被中断了,资源会不会被回收,为了更方便、更清楚的观察到回收的情况,我们需要新写一个类,然后重写finalize方法,下面我们来进行这个实验:

    public class Student {
        @Override
        protected void finalize() throws Throwable {
            System.out.println("Student 被回收了");
        }
    }
    
    public static void main(String[] args) {
            Student student = new Student();
            student = null;
            System.gc();
    }
    

    运行结果:

    Student 被回收了
    

    可以很清楚的看到资源被回收了。

    当然,在实际开发中,千万不要重写finalize方法

    在实际的开发中,看到有一些对象被手动赋值为NULL,很大可能就是为了“特意提醒”JVM这块资源可以进行垃圾回收了。

    软引用

    下面先来看看如何创建一个软引用:

     SoftReference<Student>studentSoftReference=new SoftReference<Student>(new Student());
    

    软引用就是把对象用SoftReference包裹一下,当我们需要从软引用对象获得包裹的对象,只要get一下就可以了:

    SoftReference<Student>studentSoftReference=new SoftReference<Student>(new Student());
    Student student = studentSoftReference.get();
    System.out.println(student);
    

    软引用有什么特点呢:当内存不足,会触发JVM的GC,如果GC后,内存还是不足,就会把软引用的包裹的对象给干掉,也就是只有在内存不足,JVM才会回收该对象。

    还是一样的,必须做实验,才能加深印象:

    SoftReference<byte[]> softReference = new SoftReference<byte[]>(new byte[1024*1024*10]);
    System.out.println(softReference.get());
    System.gc();
    System.out.println(softReference.get());
    
    byte[] bytes = new byte[1024 * 1024 * 10];
    System.out.println(softReference.get());
    

    我定义了一个软引用对象,里面包裹了byte[],byte[]占用了10M,然后又创建了10Mbyte[]。

    运行程序,需要带上一个参数:

     -Xmx20M
    

    代表最大堆内存是20M。

    运行结果:

    [B@11d7fff
    [B@11d7fff
    null
    

    可以很清楚的看到手动完成GC后,软引用对象包裹的byte[]还活的好好的,但是当我们创建了一个10M的byte[]后,最大堆内存不够了,所以把软引用对象包裹的byte[]给干掉了,如果不干掉,就会抛出OOM。

    软引用到底有什么用呢?比较适合用作缓存,当内存足够,可以正常的拿到缓存,当内存不够,就会先干掉缓存,不至于马上抛出OOM。

    弱引用

    弱引用的使用和软引用类似,只是关键字变成了WeakReference:

            WeakReference<byte[]> weakReference = new WeakReference<byte[]>(new byte[1024*1024*10]);
            System.out.println(weakReference.get());
    

    弱引用的特点是不管内存是否足够,只要发生GC,都会被回收:

            WeakReference<byte[]> weakReference = new WeakReference<byte[]>(new byte[1]);
            System.out.println(weakReference.get());
            System.gc();
            System.out.println(weakReference.get());
    

    运行结果:

    [B@11d7fff
    null
    

    可以很清楚的看到明明内存还很充足,但是触发了GC,资源还是被回收了。弱引用在很多地方都有用到,比如ThreadLocal、WeakHashMap。

    虚引用

    虚引用又被称为幻影引用,我们来看看它的使用:

            ReferenceQueue queue = new ReferenceQueue();
            PhantomReference<byte[]> reference = new PhantomReference<byte[]>(new byte[1], queue);
            System.out.println(reference.get());
    

    虚引用的使用和上面说的软引用、弱引用的区别还是挺大的,我们先不管ReferenceQueue 是个什么鬼,直接来运行:

    null
    

    竟然打印出了null,我们来看看get方法的源码:

        public T get() {
            return null;
        }
    

    这是几个意思,竟然直接返回了null。

    这就是虚引用特点之一了:无法通过虚引用来获取对一个对象的真实引用。

    那虚引用存在的意义是什么呢?这就要回到我们上面的代码了,我们把代码复制下,以免大家再次往上翻:

            ReferenceQueue queue = new ReferenceQueue();
            PhantomReference<byte[]> reference = new PhantomReference<byte[]>(new byte[1], queue);
            System.out.println(reference.get());
    

    创建虚引用对象,我们除了把包裹的对象传了进去,还传了一个ReferenceQueue,从名字就可以看出它是一个队列。

    虚引用的特点之二就是 虚引用必须与ReferenceQueue一起使用,当GC准备回收一个对象,如果发现它还有虚引用,就会在回收之前,把这个虚引用加入到与之关联的ReferenceQueue中。

    我们来用代码实践下吧:

            ReferenceQueue queue = new ReferenceQueue();
            List<byte[]> bytes = new ArrayList<>();
            PhantomReference<Student> reference = new PhantomReference<Student>(new Student(),queue);
            new Thread(() -> {
                for (int i = 0; i < 100;i++ ) {
                    bytes.add(new byte[1024 * 1024]);
                }
            }).start();
    
            new Thread(() -> {
                while (true) {
                    Reference poll = queue.poll();
                    if (poll != null) {
                        System.out.println("虚引用被回收了:" + poll);
                    }
                }
            }).start();
            Scanner scanner = new Scanner(System.in);
            scanner.hasNext();
        }
    

    运行结果:

    Student 被回收了
    虚引用被回收了:java.lang.ref.PhantomReference@1ade6f1
    

    我们简单的分析下代码:

    第一个线程往集合里面塞数据,随着数据越来越多,肯定会发生GC。
    第二个线程死循环,从queue里面拿数据,如果拿出来的数据不是null,就打印出来。

    从运行结果可以看到:当发生GC,虚引用就会被回收,并且会把回收的通知放到ReferenceQueue中。

    虚引用有什么用呢?在NIO中,就运用了虚引用管理堆外内存。

    以上就是这篇博客的所有内容了。

    链接:juejin.im/post/5e65b8096fb9a07cbb6e4a43

    推荐阅读

    JVM系列--还不会选择合适的垃圾收集器?

    JVM系列--彻底搞清楚怎么确定一个对象是垃圾对象?

    JVM系列--聊聊String类的intern方法和常量池

    JVM系列--运行时数据区

    JVM系列--5个常用的命令与示例

    JVM系列--JVM参数及如何设置

    展开全文
  • 强软弱虚引用区别

    2020-09-21 21:49:26
  • 强软弱虚四种引用介绍

    千次阅读 2020-10-29 18:56:21
    强软弱虚四种引用 1. User u = new User() 正常写的引用都是强引用,JVM会根据是否可达判断是否要回收。 2.软 SoftReference<byte[]> res = new SoftReference<>(new byte[1024]); res里面的byte...
  • Java中有四种引用类型:引用、软引用、弱引用、虚引用。 Java为什么要设计这四种引用 Java的内存分配和内存回收,都不需要程序员负责,都是由伟大的JVM去负责,一个对象是否可以被回收,主要看是否有引用指向此...
  • 软引用、弱引用、虚引用,全都继承自同一个抽象类,这个抽象类Reference,这个抽象类实现了引用类的主要方法,另外三个对它的扩展很少。看了一下 java 8 的源码软引用只是添加了个时间戳,弱引用什么都没添加,虚引...
  • 强引用-FinalReference介绍:强引用是平常中使用最多的引用强引用在程序内存不足(OOM)的时候也不会被回收,使用方式:String str = new String("str");这个str就是强引用。可用场景:地球人都知道,但是我讲不出来...
  • Java中的强软弱虚引用

    2011-09-27 15:50:37
    笔者自己的通俗总结,5分钟搞清楚java中强软弱虚引用区别^_^
  • 强软弱虚四大引用详解及作用 整体架构 强引用 强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OOM,也不会靠随意回收具有强引用的对象来解决...
  • 强引用 特点:我们平常典型编码Object obj = new Object()中的obj就是强引用。通过关键字new创建的对象所关联的引用就是强引用。 当JVM内存空间不足,JVM宁愿抛出OutOfMemoryError运行时错误(OOM),使程序异常...
  • 主要给大家介绍了关于java中引用类型之强软弱虚的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
  • 虚引用二、引用:1. 正常创建的对象,只要引用存在,永远不会被GC回收,即使OOMObject obj = new Object();2. 如果要中断引用和某个对象的关联,为其赋值null,这样GC就会在合适的时候回收对象3. Vector类的...
  • 强软弱虚四种引用

    2020-08-11 22:55:39
    引用与对象 在 JDK1.2 之前,Java中的定义很传统:如果 reference 类型的数据中存储的数值代表的是另外一块内存的起始地址,就称为这块内存代表着一个引用。 Java 中的垃圾回收机制在判断是否回收某个对象的时候,...
  •  在JDK1.2以前的版本中,当一个对象不被任何变量引用,那么程序就无法再使用这个对象。也就是说,只有对象处于可触及状态,程序才能使用它。这 就像在日常生活中,从商店购买了某样物品后,如果有用,就一直保留它...
  • 强软弱虚引用

    2020-06-21 19:05:15
    强软弱虚,是 Java 中比较主流的四种引用。(多念念,就顺口了) 从这四种引用的作用来看(接下来你会看到),引用,与对象的存活密不可分。也许正是因为有了 JVM 的垃圾收集器,才有了这四种引用。 我觉得直接看四...
  • 强软弱虚引用、软引用、弱引用、虚引用)对应的是四种JVM回收堆内存的四种策略,不同的引用类型有不同的回收策略。 (1)引用 package basic.RefTypeAndThreadLocal; import java.io.IOException; /** ...
  • 引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)总结:引用:不管内存够不够都不会被回收(我们平时new创建对象就是引用)软引用:内存够用不回收,不够用...
  • 强软弱虚引用.

    2020-10-19 22:33:45
    强软弱虚引用. 引用: 他是我们最常见的引用object o=new Object();这个就是引用.当我们修改他为null时他才可能被回收.o=null;因为他不存在指向了. 软引用: 垃圾回收器,内存不够的时候回收. 使用软引用需要导包....
  • JVM 强软弱虚引用

    2020-06-28 14:31:16
    强软弱虚 强引用: Object obj = new Object(); 当内存空间满了之后 obj 也不会被回收 可以使用 obj = null; 让垃圾回收器进行回收 软引用: SoftReference softReference = new SoftReference(new Object()); 只有当...
  • Java 强软弱虚 引用

    2020-05-17 18:23:10
    强引用 : A a = new A (); 这就是强引用,只有a = null 或者a 不在指向堆中的 a 对象, a对象才会被jvm 回收 软引用:
  • java强软弱虚引用

    2020-04-13 23:11:50
    1、强引用—用new 当我们用new向堆区申请一片内存空间时,此时就是强引用。 当内存不足,GC(垃圾收集器)不会回收该强引用的对象。 2、软引用—用SofeReference类实现 用来描述一些还有用但并非必需的对象。 ...
  • java中的引用类型共4种:强软弱虚,具体每种类型的特点和应用场景。记录下。本文是看了马士兵老师的视频后记录整理的。加深印象。基本概念1. 强引用强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器...
  • 以前学习强软弱虚引用的时候,只是走马观花看看博客,并没有自己写代码去实践、去证明,导致每次看完后,过不了多久就忘了,后来下定决心,一定要自己敲敲代码,这样才能让印象更加深刻,古人云:纸上得来终觉浅,绝...
  • java强软弱虚引用总结

    2020-10-02 18:34:07
    1、强引用(死也不回收) new出来的对象 ,死也不回收 OOM的主要原因之一 2、软引用(不够即回收) 内存够时不清空,内存不够时 执行二次回收,回收后依然不够后报OOM User u = new User(); SoftReference<...
  • Java 强软弱虚引用

    2019-10-04 12:23:59
    Java 强软弱虚引用 Java 根据对象的引用方式可以分为:引用、软引用、弱引用、虚引用。 即 SoftReference、WeakReference、PhantomReference。 SoftReference、WeakReference、PhantomReference 位于 java.lang....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,827
精华内容 730
关键字:

强软弱虚引用的区别