精华内容
下载资源
问答
  • 主要介绍了Java四种引用类型详细介绍的相关资料,需要的朋友可以参考下
  • 主要介绍了Java对象的四种引用方式,简单描述了四种引用方式的概念、应用场景并结合实例形式分析了弱引用引用对象的垃圾回收过程,需要的朋友可以参考下
  • JAVA中的引用四种引用类型

    千次阅读 2020-08-30 10:09:38
    关于值类型和引用类型的话题,C++、JAVA、python、go、C#等等高级语言都有相关的概念,只要理解了其底层工作原理,可以说即使是不同的语言,在面试学习工作实践中都可以信手拈来(不要太纠集语言),当然此处我选择了...

    关于值类型和引用类型的话题,C++、JAVA、python、go、C#等等高级语言都有相关的概念,只要理解了其底层工作原理,可以说即使是不同的语言,在面试学习工作实践中都可以信手拈来(不要太纠集语言),当然此处我选择了JAVA,虽然我是搞C++的,具体原因都懂就不废话了。

    一、值类型与引用类型

      1、变量初始化

    int num=10;
    String str="hello"

      

      2、变量赋值
       从上图可以显而易见,num是int基本类型变量,值就直接保存在变量中。str是String引用类型变量,变量中保存的只是实际对象对应的地址信息,而不是实际对象数据。对于而这特性,如下:

    num=20;
    str="java";

      对于基本类型变量num,赋值运算符将会直接修改变量的值,原来的数据将被覆盖掉,被替换为新的值。对于引用类型变量str,赋值运算符只会改变变量中所保存的对象的地址信息,原来对象的地址被覆盖掉,重新写入新对象的地址数据。但原来的对象本身并不会被改变,只是不再被任何引用所指向的对象,即“垃圾对象”,后续会被垃圾回收器回收。

      3、函数传参

     

    // 基本类型参数,原始value不会被更改
        public void func(int value) {
            value = 100;
        }
    
        // 对于没有提供修改自身的成员方法引用类型,原始str不会被更改
        public void func(String str) {
            str = "hello";
        }
    
        StringBuilder sb = new StringBuilder("test");
    
        // 对于提供修改自身的成员方法引用类型,原始的sBuilder会被更改
        public void func(StringBuilder sBuilder) {
            sBuilder.append("aa");
        }
    
        // 原始的sBuilder不会被更改
        public void test(StringBuilder sBuilder) {
            sBuilder = new StringBuilder("111");
        }

     

    说明:对于第三种情况:

    对于第四种情况:

     

     

    二、数据存储方式

      1、局部变量/方法参数

      对于局部变量和方法传递的参数在jvm中的存储方式是相同的,都是存储在栈上开辟的空间中。方法参数空间在进入方法时开辟,方法退出时进行回收。以32为JVM为例,boolean、byte、short、char、int、float以及对应的引用类型都是分配4字节大小的空间,long、double分配8字节大小空间。对于每一个方法来说,最多占用空间大小是固定的,在编译时就已经确定了。当在方法中声明一个int变量i=0或Object变量obj=null时,此时仅仅在栈上分配空间,不影响到堆空间。当new Object()时,将会在堆中开辟一段内存空间并初始化Object对象。

      2、数组类型引用和对象

      当声明数组时,int[]  arr=new int[2];数组也是对象,arr实际上是引用,栈上占用4个字节大小的存储空间,而是会在堆中开辟相应大小空间进行存储,然后arr变量指向它。当声明一个二维数组时,如:int[][]  arr2=new int[2][4],arr2同样在栈中占用4个字节,在堆内存中开辟长度为2,类型为int[]的数组对象,然后arr2指向这个数组。这个数组内部有两个引用类型(大小为4个字节),分别指向两个长度为4类型为int的数组。内存分布如图:

    所以当传递一个数组给一个方法时,数组的元素在方法内部是可以被修改的,但是无法让数组引用指向新的数组。其实,还可以声明:int [][]  arr3=new int[3][],内存分布如下:

      3、String类型数据

      对于String类型,其对象内部需要维护三个成员变量,char[]  chars,int  startIndex,  int  length。chars是存储字符串数据的真正位置,在某些情况下是可以共用的,实际上String类型是不可变类型。例如:String  str=new String("hello"),内存分布如下:

     

    三、JAVA引用类型

      在JAVA中提供了四种引用类型:强引用、软引用、软引用和虚引用。在四种引用类型中,只有强引用FinalReference类型变量是包内可见的,其他三种引用类型均为public,可以在程序中直接使用。

      1、强引用

      强引用是使用最普遍的引用。如果一个对象具有强引用,那么垃圾回收器绝不会回收它。例如:StringBuilder sb = new StringBuilder("test");变量str指向StringBuffer实例所在的堆空间,通过str可以操作该对象。如下:

      强引用特点:

      • 强引用可以直接访问目标对象
      • 只要有引用变量存在,垃圾回收器永远不会回收。JVM即使抛出OOM异常,也不会回收强引用所指向的对象。
      • 强引用可能导致内存泄漏问

       2、软引用

      软引用是除了强引用外,最强的引用类型。可以通过java.lang.ref.SoftReference使用软引用。一个持有软引用的对象,不会被JVM很快回收,JVM会根据当前堆的使用情况来判断何时回收。当堆使用率临近阈值时,才会去回收软引用的对象。因此,软引用可以用于实现对内存敏感的高速缓存。SoftReference的特点是它的一个实例保存对一个Java对象的软引用,该软引用的存在不妨碍垃圾收集线程对该Java对象的回收。也就是说,一旦SoftReference保存了对一个Java对象的软引用后,在垃圾线程对 这个Java对象回收前,SoftReference类所提供的get()方法返回Java对象的强引用。一旦垃圾线程回收该Java对象之后,get()方法将返回null。

    Object obj = new Object();
    SoftReference<Object> sf = new SoftReference<Object>(obj);
    obj = null;
    sf.get();//有时候会返回null
    sf是对obj的一个软引用,通过sf.get()方法可以取到这个对象,当这个对象被标记为需要回收的对象时,则返回null;

      软引用主要用户实现类似缓存的功能,在内存足够的情况下直接通过软引用取值,无需从繁忙的真实来源查询数据,提升速度;当内存不足时,自动删除这部分缓存数据,从真正的来源查询这些数据。使用软引用能防止内存泄露,增强程序的健壮性。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。也就是说,ReferenceQueue中保存的对象是Reference对象,而且是已经失去了它所软引用的对象的Reference对象。当调用它的poll()方法的时候,如果这个队列中不是空队列,那么将返回队列前面的那个Reference对象。在任何时候,都可以调用ReferenceQueue的poll()方法来检查是否有它所关心的非强可及对象被回收。如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。利用这个方法,可以检查哪个SoftReference所软引用的对象已经被回收,于是可以把这些失去所软引用的对象的SoftReference对象清除掉。

      3、弱引用

      弱引用是一种比软引用较弱的引用类型。在系统GC时,只要发现弱引用,不管系统堆空间是否足够,都会将对象进行回收。在java中,可以用java.lang.ref.WeakReference实例来保存对一个Java对象的弱引用。弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。弱引用主要用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnQueued方法返回对象是否被垃圾回收器标记。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

    Object obj = new Object();
    WeakReference<Object> wf = new WeakReference<Object>(obj);
    obj = null;
    wf.get();//有时候会返回null
    wf.isEnQueued();//返回是否被垃圾回收器标记为即将回收的垃圾

      4、虚引用

      虚引用是所有类型中最弱的一个。一个持有虚引用的对象和没有引用几乎是一样的,随时可能被垃圾回收器回收,当试图通过虚引用的get()方法取得强引用时,总是会失败。并且虚引用必须和引用队列一起使用,它的作用在于检测对象是否已经从内存中删除,跟踪垃圾回收过程。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在垃圾回收后,销毁这个对象,将这个虚引用加入引用队列。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

    Object obj = new Object();
    PhantomReference<Object> pf = new PhantomReference<Object>(obj);
    obj=null;
    pf.get();//永远返回null
    pf.isEnQueued();//返回是否从内存中已经删除

     

     

    @Test
        public void test(){
            Map map;
            map = new WeakHashMap<String,Object>();
            for (int i =0;i<10000;i++){
                map.put("key"+i,new byte[i]);
            }
    //        map = new HashMap<String,Object>();
    //        for (int i =0;i<10000;i++){
    //            map.put("key"+i,new byte[i]);
    //        }
        }

     

      使用-Xmx2M限定堆内存,使用WeakHashMap的代码正常运行结束,而使用HashMap的代码段抛出异常:java.lang.OutOfMemoryError: Java heap space。由此可见,WeakHashMap会在系统内存紧张时使用弱引用,自动释放掉持有弱引用的内存数据。但如果WeakHashMap的key都在系统内持有强引用,那么WeakHashMap就退化为普通的HashMap,因为所有的数据项都无法被自动清理。

    展开全文
  • Java四种引用类型

    万次阅读 多人点赞 2019-05-12 19:01:34
    文章目录引用类型简介对象可达性判断GC Roots对象可达性判断可达性状态类型可达性判断规则状态转换Reference类定义状态变化四种引用类型实现强引用FinalReference软引用SoftReference弱引用WeakReference虚引用...

    引用类型简介

    Java开发者肯定都很熟悉java中的4种引用类型,它们从强到弱分别是:

    引用类型对象是否可引用回收时间使用场景
    强引用可以从不回收普遍对象的状态
    软引用可以内存不足时内存敏感的高速缓存
    弱引用可以下一次GC对象缓存
    虚引用不可以下一次GC,不影响对象生命周期必须和引用队列(ReferenceQueue)一起使用,一般用于追踪垃圾收集器的回收动作。相比对象的finalize方法,虚引用的方式更加灵活和安全。

    但可能大多数对4种引用类型的理解都只停留在概念的记忆上,而并不了解四种引用的实现原理。下面我们结合源代码了解下四种引用的实现原理。当然在了解四种引用的实现原理之前,首先得了解下JVM中实现对象可达性判断的原理。

    对象可达性判断

    目前,大多数JVM都是使用可达性分析算法来判断对象的是否可达。可达性分析算法以GC Roots对象作为起始点进行搜索。当一个对象与GC Roots对象没有任何引用链相连时(也即引用有向图中从GC Roots对象到这个对象是不连通的),则表明该对象是不可用的(不可用的对象不一定被判定为可以回收的对象)。当对象与GC Roots对象有引用链相连时,则需要根据引用链的类型来判断对象是否可达。

    不可用的对象不一定被判定为可以回收的对象:判定对象为”死亡”至少需要经历两次标记的过程。第一次标记:对象可达性分析,如果发现对象没有与GC Roots相连接的引用链,且对象需要执行finalize方法,将会被加入F-Queue队列中。第二次标记:由一个优先级低的Finalizer线程去取F-Queue队列的对象,“尝试执行”对象的finalize方法。

    JVM会保证触发满足条件的对象的finalize方法,但是并不承诺会等待方法执行结束。finalize方法是对象逃脱死亡命运的最后一次机会。

    GC Roots对象

    GC Roots对象包含以下四类:

    • 虚拟机栈(栈桢中的本地变量表)中的引用的对象;
    • 方法区中的类静态属性引用的对象;
    • 方法区中的常量引用的对象;
    • 本地方法栈中JNI(Native方法)引用的对象;

    可达性判断

    可达性状态类型

    Java有5种类型的可达性状态:

    • 强可达(Strongly Reachable):与GC Roots对象之间有强引用相连通,则为强可达的;
    • 软可达(Soft Reachable):与GC Roots对象之间没有强引用相连通,但有软引用相连通,则为软可达的;
    • 弱可达(Weak Reachable):与GC Roots对象之间没有强引用或软引用相连通,但有弱引用相连通,则为弱可达的;
    • 虚可达(Phantom Reachable):与GC Roots对象之间没有强引用、软引用或弱引用相连通,然后该对象finalize方法已执行,并且有虚引用相连通,则为虚可达的;
    • 不可达(Unreachable):如果对象finalize方法已执行并且没有任何引用相连通,则对象是不可达的,可以被回收。

    可达性判断规则

    从GC Roots对象到一个对象的引用链可能存在多条,那么此时会依据两个原则来判断对象的可达性:

    • 单个引用链中,以最弱的引用类型为准;
    • 多引用链联合看时,以最强的引用类型为准;

    可达性判断

    首先,单个引用链中,以最弱的引用类型为准:则GC Roots->Obj1->Obj4是软引用连通的,GC Roots->Obj2->Obj4是弱引用连通的,GC Roots->Obj3->Obj5是弱引用连通的。然后多引用链联合看时,以最强的引用类型为准:则GC Roots到Obj4对象的引用联合来看是弱引用连通的。

    状态转换

    对象可达性状态是随着程序运行而不断变化的,对象可达性状态转换图可参考下图。

    • 对象创建后一般是强可达的。
    • 当GC Roots对象到该对象的强引用被清除后:如果剩余引用链最高为软引用,则状态转换为软可达的;反之如果最高为弱引用,则状态转换为弱可达的,反之则把对象标记为可执行finalize方法状态。
    • 当软可达对象重新被强引用连接时,则转换为强可达状态;当软可达对象的软引用被清除后,如果剩余引用链最高为弱引用,则状态转换为弱可达;反之则把对象标记为可执行finalize方法状态。
    • 当弱可达对象重新被强引用或者软引用连接时,则可转换为强可达或者软可达;当弱可达对象的弱引用被清除后,则把对象标记为可执行finalize方法状态。
    • 可对象被标记为可执行finalize方法状态,如果对象finalize从未被执行,则执行finalize方法,并标记对象的finalize方法已经被执行(在finalize方法可能会重新生成强/软/弱引用等,对象状态会重新转换为强/软/弱可达,不过并不推荐这么做,因为可能会导致对象状态紊乱,无法被正常回收);反之当对象有虚引用连接时,则转换为虚可达状态,否则转换为不可达状态。
    • 虚可达对象在垃圾回收后状态转换为不可达(不能通过虚引用获取对象引用,所以对象状态不会再转换为强/软/弱可达);

    可达性状态转换图

    Reference

    Reference类是所有引用类型的基类,定义了reference对象的通用操作,用来保存对象引用及引用的内部状态。Reference抽象类初始化时,会启动一个ReferenceHandler线程。Reference的referent被回收前,垃圾回收器会把reference添加到pending这个链表里(如果注册了ReferenceQueue),然后ReferenceHandler线程不断的读取pending中的reference,把它加入到对应的ReferenceQueue中(如果Reference是Cleaner类的实例,即虚引用对象,则调用其注册的预处理钩子方法)。

    ReferenceQueue提供了两个静态字段NULL,ENQUEUED。这两个字段的主要功能:NULL是当我们构造Reference实例时queue传入null时,会默认使用NULL,这样在enqueue时判断queue是否为NULL,如果为NULL直接返回,入队失败。ENQUEUED的作用是防止重复入队,reference后会把其queue字段赋值为ENQUEUED,当再次入队时会直接返回失败。

    类定义

    Reference对象的基类。该类定义了reference对象的通用操作。因为reference对象是和垃圾回收器密切配合实现的,因此该类不能直接进行子类化。

    public abstract class Reference<T> {
    	// 用于保存对象的引用,GC会特别对待该变量
        private T referent; 
    	// 如果注册了ReferenceQueue(需要通知机制),用来保存对象引用的队列,
        volatile ReferenceQueue<? super T> queue;
    
        // 保存需要由ReferenceHandler处理的引用
        volatile Reference next;
    
    	// 被JVM使用,保存需要被JVM处理的下一个引用
        transient private Reference<T> discovered;
    
        // 同步锁,用于同步pending队列的进队和出队
        static private class Lock { }
        private static Lock lock = new Lock();
    
        // 一个PENDING队列,配合上述next一起使用,实现类单向循环链表的操作
        private static Reference<Object> pending = null;
    
    	// 高优先级线程,用于将pending队列里面的Reference实例依次添加到不同的ReferenceQueue中
    	private static class ReferenceHandler extends Thread {...}
    	...
    }
    

    状态变化

    一个对象引用有四种内部状态:

    • Active: 新创建的实例的状态,当对象引用被垃圾回收器回收前:如果Reference注册了ReferenceQueue,则会切换为Pending,并且Reference会加入pending链表中,如果没有注册ReferenceQueue,会切换为Inactive。
    • Pending: 在pending链表中的Reference的状态,这些Reference等待被ReferenceHandler内部线程加入ReferenceQueue中。
    • Enqueued: 在ReferenceQueue队列中的Reference的状态,如果Reference从队列中移除,会进入Inactive状态。未注册ReferenceQueue的实例不会到达该状态。
    • Inactive: Reference的最终状态,该状态不会再改变。

    其状态转换图如下:

    Reference内部状态转换图

    四种引用类型实现

    不同引用类型的UML类图如下:

    Reference UML类图

    强引用FinalReference

    对象新建后默认为强引用类型的,是普遍对象引用的类型。查看FinalReference在JDK中的源码发现其只有一个空实现,这也说明强引用是“默认引用类型”。

    /**
     * Final references, used to implement finalization
     */
    class FinalReference<T> extends Reference<T> {
        public FinalReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
        }
    }
    

    软引用SoftReference

    软引用是用来描述一些“还有用但是非必须”的对象。软引用的回收策略在不同的JVM实现会略有不同,JVM不仅仅只会考虑当前内存情况,还会考虑软引用所指向的referent最近的使用情况和创建时间来综合决定是否回收该referent。软引用保存了两个变量:

    • timestamp:每次调用get方法都会更新时间戳。JVM可以利用该字段来选择要清除的软引用,但不是必须要这样做。
    • clock:时间锁,由垃圾收集器更新。

    因此,任何GC都可以使用这些字段并定义清除软引用的策略,例如:最后清除最近创建的或最近使用的软引用。

    /**
     * 软引用对象由垃圾收集器根据内存需要决定是否清除。软引用经常用于实现内存敏感的缓存。
     *
     * 假如垃圾收集器在某个时间确定对象是软可达的,此时它可以选择原子地清除
     * 指向该对象的所有软引用,以及从该对象通过强引用链连接的其他软可达对象的所有软引用。
     * 与时同时或者之后的某个时间,它会将注册了reference queues的新清除的软引用加入队列。
     *
     * 在虚拟机抛出OutOfMemoryError异常之前,将保证清除对软可达对象的所有软引用。
     * 不过,并没有对清除软引用的时间以及清除顺序施加强制约束。
     * 但是,鼓励虚拟机实现偏向不清除最近创建或最近使用的软引用。
     *
     * 该类的直接实例可用于实现简单的缓存。
     * 该类或其派生子类也可用于更大的数据结构以实现更复杂的高速缓存。
     * 只要软引用的引用对象还是强可达的,即还在实际使用中,软引用就不会被清除。
     * 因此,复杂的高速缓存可以通过持有对最近使用缓存对象的强引用来防止其被清除,
     * 而不常使用的剩余缓存对象由垃圾收集器决定是否清除。
     */
    public class SoftReference<T> extends Reference<T> {
    
    	// 时间锁,由垃圾收集器更新。
        static private long clock;
    
    	// 每次调用get方法都会更新该时间戳。JVM可能会在选择要清除的软引用时使用该字段,
    	// 但这不是强制必须的。
        private long timestamp;
    	
    	// 返回对象的引用。如果该引用对象已经被程序或者垃圾收集器清除,则返回null。
    	// 把最近一次垃圾回收时间赋值给timestamp
        public T get() {
            T o = super.get();
            if (o != null && this.timestamp != clock)
                this.timestamp = clock;
            return o;
        }
    
    }
    

    弱引用WeakReference

    当一个对象没有被强引用或者软引用连接,但被弱引用连接时,则处于弱可达状态。只要发生GC,弱可达的对象就会被清除,同时会把弱引用加入到注册的引用队列中(如果存在的话)。弱引用对GC几乎是没有影响的,它不影响对应的referent被终结(finalized)和回收(reclaimed)。因此,弱引用最常用于实现规范化映射(canonicalizing mappings),例如哈希表,如果它们在程序中未被引用,则其键和值将从映射中删除。

    /**
     * 弱引用对象不能阻止自身的引用被回收。
     * 弱引用常用于实现规范化映射(对象实例可以在程序的多个地方同时使用)。
     *
     * 假如垃圾收集器在某个时间点确定对象是弱可达的。那时它将原子地清除对该对象的所有弱引用
     * 以及该引用通过强引用或者软引用连接的所有其他弱可达对象的所有弱引用。
     * 同时,它将表明前面所指的所有弱可达对象都可以执行finalize方法。
     * 与此同时或之后某一个时间,它将注册了reference queues的那些新清除弱引用加入队列。
     */
    public class WeakReference<T> extends Reference<T> {
    
    	// 创建没有注册ReferenceQueue的弱引用
        public WeakReference(T referent) {
            super(referent);
        }
    
    	// 创建注册了ReferenceQueue的弱引用
        public WeakReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
        }
    }
    

    虚引用PhantomReference

    虚引用是所有引用类型中最弱的一种。一个对象是否关联到虚引用,完全不会影响该对象的生命周期,也无法通过虚引用来获取一个对象的实例。为对象设置一个虚引用的唯一目的是:能在此对象被垃圾收集器回收的时候收到一个系统通知,它就是利用ReferenceQueue实现的。当referent被gc回收时,JVM自动把虚引用对象本身加入到ReferenceQueue中,表明该reference指向的referent被回收。然后可以通过去queue中取到reference,可以通过这个来做额外的清理工作。可以用虚引用代替对象finalize方法来实现资源释放,这样更加灵活和安全。

    /**
     * 虚引用对象在被垃圾收集器检查到后加入reference queues队列,否则会被回收。
     * 虚引用最常用于实现比Java finalization机制更灵活的安排额外的清理工作。
     *
     * 如果垃圾收集器在某个时间点确定虚引用对象是虚可达的,那么在那个时间或之后某个时间它会将引用加入reference queues队列。
     *
     * 为了确保可回收对象保持不变,虚引用的引用无法使用:虚引用对象的get方法始终返回null。
     *
     * 与软引用和弱引用不同,当虚引用加入reference queues队列后垃圾收集器不会被自动清除。
     * 只通过虚引用可达的对象将保持不变,直到所有此类引用都被清除或自已变为不可达。
     */
    public class PhantomReference<T> extends Reference<T> {
    
        // 由于不能通过虚引用访问对象,因此此方法始终返回null。
        public T get() {
            return null;
        }
    
        // 使用空ReferenceQueue队列创建一个虚引用没有意义:它的get方法总是返回null,
    	// 并且由于它没有注册队列,所以也不会被加入队列有任何清理前的预处理操作。
        public PhantomReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
        }
    }
    
    展开全文
  • Java四种引用类型有哪些?

    千次阅读 2021-02-12 11:01:54
    学过Java的人们都知道,Java的类型一般有两,一是基本数据类型,另一引用数据类型。其中,基本数据类型的值通常储存与栈内存,用于...因此四种引用类型可以说是大家在学习Java的过程中经常会接触到的。那么...

    学过Java的人们都知道,Java的类型一般有两种,一种是基本数据类型,另一种是引用数据类型。其中,基本数据类型的值通常储存与栈内存,用于对该类型的对象进行存储;而引用数据类型则在存储堆中对需要引用的对象进行引用。

    说到引用,引用是Java面向对象的一个特点,如果一个对象不曾被任何变量应用的话,那么整个程序也就无法再使用这一对象。因此四种引用类型可以说是大家在学习Java的过程中经常会接触到的。那么Java究竟有哪四种引用类型呢?

    类型一:强引用

    强引用是一种最常见的引用形式,同时也较为普遍。如果内存空间不足,Java虚拟机将会抛出OutOfMemoryError错误,从而程序将异常停止。强引用的对象是不可以GC回收的,不可以随意回收具有强引用的对象来解决内存不足的问题。把一个对象赋给一个引用类型变量,则为强引用。在Java中,强引用是一种默认的状态,除非JVM虚拟机停止工作。

    类型二:软引用

    软引用和强引用不同,如果内存空间足够多,一个对象被软引用,则垃圾回收器不会将其回收;如果内存空间不足,这些引用对象就会被回收。所以,软引用就是当回收器没有回收某个对象时,程序就可以对其使用。它可用来较为敏感的高速缓存,虚拟机可以将软引用加入到与之向关联的队列。

    类型三:弱引用

    弱引用的特点就是引用对象的生命周期较短。G回收器在扫描内存区域是若发现弱引用,即便是内存空间还足够使用,弱引用对象都会被回收。但弱引用对象也可以加入队列,这样就可以不被回收。

    类型四:虚引用

    从这种引用类型的名称就可以看出,虚引用的对象可以说是形同虚设。为什么这么说呢?因为虚引用不会决定对象的生命周期,并且虚引用等于没有引用,随时都可以被GC回收。

    四种引用类型是Java学习的重要部分。以后在实战中也是经常需要用到的,因此在记熟基础知识点之后,不妨多自己动手写写代码。网上开源的代码虽然有许多可以借鉴,但是在学习的时候,还是尽量自己动手去写,网上的代码再好,也是别人的技术,毕竟只有自己能够写出来的代码才算是自己的技术。

    展开全文
  • JAVAjava中的四种引用

    万次阅读 多人点赞 2018-08-25 13:43:34
    java中的四种引用 JDK1.2之后,把对象的引用分为四种状态,即强引用、软引用、弱引用和虚引用。这样的方式,可以更加灵活地控制对象的生命周期。 一、强引用 开发中用的最多的就是强引用了。 强引用声明格式...

                                           java中的四种引用

     

    JDK1.2之后,把对象的引用分为四种状态,即强引用、软引用、弱引用和虚引用。这样的方式,可以更加灵活地控制对象的生命周期。

     

    一、强引用

    开发中用的最多的就是强引用了。

    强引用声明格式:

    String str="abc";
    

    只要某个对象与强引用关联,那么JVM在内存不足的情况下,宁愿抛出outOfMemoryError错误,也不会回收此类对象

     

    【1】如果我们想要JVM回收此类被强引用关联的对象,我们可以显示地将str置为null,那么JVM就会在合适的时间回收此对象。

     

    二、软引用

    java中使用SoftRefence来表示软引用,如果某个对象与软引用关联,那么JVM只会在内存不足的情况下回收该对象

    那么利用这个特性,软引用可以用来做缓存。

    软引用声明格式:

    import java.lang.ref.SoftReference;
    
    public class TestRef {
        public static void main(String args[]) {
            SoftReference<String> str = new SoftReference<String>(new String("abc"));
            System.out.println(str.get());
            //通知JVM进行内存回收
            System.gc();
            System.out.println(str.get());
        }
    }
    

    输出:

    可以看得出来,此时JVM内存充足,暂时还没有回收被软引用关联的对象。

    【1】软引用适合做缓存,在内存足够时,直接通过软引用取值,无需从真实来源中查询数据,可以显著地提升网站性能。当内存不足时,能让JVM进行内存回收,从而删除缓存,这时候只能从真实来源查询数据。

     

     

    三、弱引用

     

    java中使用WeakReference来表示弱引用。如果某个对象与弱引用关联,那么当JVM在进行垃圾回收时,无论内存是否充足,都会回收此类对象

    弱引用声明格式:

    import java.lang.ref.WeakReference;
    
    public class TestRef {
        public static void main(String args[]) {
            WeakReference<String> str = new WeakReference<String>(new String("abc"));
            System.out.println(str.get());
            //通知JVM进行内存回收
            System.gc();
            System.out.println(str.get());
        }
    }

    输出:

    可以看得出来,被弱引用关联的对象,总是会在垃圾回收时被回收掉。

    注意:(1)System.out.println(str.get());有可能取不到str的值。这是因为我们在声明了弱引用之后,立即对其输出,而gc线程是一个优先级很低的守护线程,还来不及扫描该该对象所在的区域,即来不及对该对象的回收。如果我们在声明之后的很长时间后,再次get,是有可能get不到值的。

     

    【1】弱引用可以在回调函数在防止内存泄露。因为回调函数往往是匿名内部类,一个非静态的内部类会隐式地持有外部类的一个强引用,当JVM在回收外部类的时候,此时回调函数在某个线程里面被回调的时候,JVM就无法回收外部类,造成内存泄漏。在安卓activity内声明一个非静态的内部类时,如果考虑防止内存泄露的话,应当显示地声明此内部类持有外部类的一个弱引用。

     

    四、虚引用

    java中使用PhantomReference来表示虚引用。虚引用,虚引用,引用就像形同虚设一样,就像某个对象没有引用与之关联一样。若某个对象与虚引用关联,那么在任何时候都可能被JVM回收掉。虚引用不能单独使用,必须配合引用队列一起使用。

    虚引用声明格式:

    import java.lang.ref.PhantomReference;
    import java.lang.ref.ReferenceQueue;
    
    
    public class TestRef {
        public static void main(String args[]) {
            ReferenceQueue<String> queue = new ReferenceQueue<>();
            PhantomReference<String> str = new PhantomReference<String>("abc", queue);
            System.out.println(str.get());
    
        }
    }
    

    输出:

    可见使用get方法无法获取该对象的值

     

    【1】当垃圾回收器准备回收一个对象时,如果发现它与虚引用关联,就会在回收它之前,将这个虚引用加入到引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被回收,如果确实要被回收,就可以做一些回收之前的收尾工作。

    展开全文
  • 详解 Java 中的四种引用

    万次阅读 2018-10-13 23:00:36
    Java 中,引用随处可见,我们通过类似 Object obj = new Object(); 的代码就可以创建一个引用,而我们直接通过这个代码段创建的引用被称为强引用(StrongReference),这种引用的特点是其指向的对象无论如何都...
  • Java四种引用方式

    万次阅读 多人点赞 2019-03-16 09:34:23
    Java中提供这四种引用类型主要有两个目的: 第一是可以让程序员通过代码的方式决定某些对象的生命周期; 第二是有利于JVM进行垃圾回收。 下面来阐述一下这四种类型引用的概念: 1.强引用 是指创建一个对象并把...
  • Java 四种引用介绍及使用场景

    万次阅读 多人点赞 2018-01-28 00:28:10
    引用-FinalReference 介绍: 强引用是平常中使用最多的引用,强引用在程序内存不足(OOM)的时候也不会被回收,使用方式: String str = new String("str"); 这个str就是强引用。 可用场景: ...
  • java四种引用类型

    千次阅读 2015-08-27 11:42:50
    今天看代码,里面有一个类java.lang.ref.SoftReference把小弟弄神了,试想一下,接触java已经有3年了哇,连lang包下面的类都不了解,怎么混。后来在网上查资料,感觉收获颇多,现记录如下。对象的强、软、弱和虚引用...
  • 浅谈 Java 四种引用类型

    千次阅读 2018-08-08 16:12:58
    今天就谈一谈 Java 对象的四种引用方法吧。 StrongReference(强引用) A a = new A(); 这就是强引用,也是最常见的引用方式。如果对象是一个强引用,那么 JVM 绝对不会回收他,绝对到哪程度呢?宁愿牺牲自己...
  • Java篇 - 四种引用(Reference)实战

    万次阅读 多人点赞 2019-01-16 18:49:35
    Java的垃圾回收(GC)是虚拟机自动管理的,...Java对象的引用包括:强引用,软引用,弱引用,虚引用Java中提供这四种引用类型主要有两个目的: 可以让程序员通过代码的方式决定某些对象的生命周期。 有利于JVM...
  • Java中的四种引用类型是哪些?

    千次阅读 2020-07-01 23:10:51
    从一开始学习Java我们就知道Java的数据类型一般有两,一是基本数据类型,另一引用...Java中主要包括了四种引用类型,分别是:强引用,软引用,弱引用以及虚引用。 一、强引用引用是一最常见的引用形式,
  • Java四种引用类型

    千次阅读 2018-05-30 21:45:16
    引用分为四种:1,强引用,2,软引用,3,弱引用,4,虚引用。   1,强引用。 就是最常用的Object obj = new Object(); obj就是一个强引用,当这个引用存在时JVM直到内存耗尽都不会回收,宁可报OOM。所以一般...
  • JAVA四种引用方式

    万次阅读 多人点赞 2016-08-03 19:20:37
    Java中提供这四种引用类型主要有两个目的: 第一是可以让程序员通过代码的方式决定某些对象的生命周期; 第二是有利于JVM进行垃圾回收。 下面来阐述一下这四种类型引用的概念: 1.强引用  是指创建一个对象
  • java中的四种引用及其使用场景

    千次阅读 2018-11-20 13:22:52
    Java的对象引用一共有四种方式:强引用,软引用,弱引用,虚引用 强引用-StrongReference 这是java中最常见的引用方式,当一个对象被一个或一个以上的引用变量所引用时,它不可能被系统垃圾回收机制回收 使用...
  • java四种引用的理解

    千次阅读 2019-04-09 10:51:14
    引用, WeakReference当一个对象只用弱引用的时候, 收集器发现它了就会回收它, 没发现就是还可以使用的 软引用, SoftReference 当内存不足的时候, 在进行fullGC之前会回收软引用, 所以使用用来作为缓存 虚引用 ...
  • 一、JAVA中的数据类型分为分为两大类: 1.基本数据类型(八): 类型名称 占用字节 数据范围 默认值 字 节 byte 1 -128 ~ 127 0 短整型 short 2 -32768 ~ 32767 0 整 型 int 4 -2^31 ~ 2^31 - 1 0 ...
  • Java中存在四种引用,它们分别是: (1)强引用(StrongReference) 强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使...
  • 四种引用类型分别为强引用,软引用,弱引用和虚引用。 所谓强引用,就是我们最常见的普通对象引用,我们 new 出来的对象就是强引用,只要尚且存在强引用指向某一个对象,那就能表明该对象还存活,GC 不能去回收...
  • Java 如何有效地避免OOM:善于利用软引用和弱引用。  想必很多朋友对OOM(OutOfMemory)这个错误不会陌生,而当遇到这种错误如何有效地解决这个问题呢?今天我们就来说一下如何利用软引用和弱引用来有效地解决程序...
  • Java基础知识学习1、Java中有哪几种引用?它们的含义和区别是什么?1) 强引用(StrongReference)强引用是使用最普遍的引用,如果一个对象具有强引用,那么垃圾回收器绝对不会回收它,当内存控件不足时,java虚拟机宁愿...
  • Java对象的四种引用

    千次阅读 2021-09-09 16:00:03
    也就是说,若一个对象不被任何变量引用,那么程序就无法再使用这个对象。垃圾回收器一旦发现这些无用对象,就会对其进行回收。但是,在某些情况下,我们会希望有些对象不需要被立即回收,或者说从全局的角度来说没有...
  • Java中的四种引用介绍和使用场景

    千次阅读 2017-07-13 15:03:56
    Java中有四种引种,我们最常见的就是强引用,就是使用new关键字创建一个对象的方式。关于这四种引用,我介绍一下他们的功能和使用场景。1、强引用(Strong Reference)功能:一个对象如果具有强引用,那么垃圾回收器...
  • Java四种引用---强、软、弱、虚的知识点总结

    千次阅读 多人点赞 2017-07-02 17:31:26
    Java四种引用
  • Java四种引用类型,strongreference,softreference,weakreference,phantomreference。这四种引用的强度按照上面的顺序依次减弱,下面通过几个例子简单了解一下这四种引用类型。 StrongReference 这个不用...
  • java四种引用的概念及应用场景

    千次阅读 2018-05-31 11:18:19
    java中存在四种引用机制,分别是强引用,软引用,弱引用,虚引用强引用一般情况下我们用new方式创建的引用就是强引用,比如Client client = new Client()jvm进行GC的时候是不会回收存在强引用的对象的,比如Server ...
  • Java四种引用之间的区别?

    千次阅读 多人点赞 2021-05-17 23:50:20
    本文隶属于专栏《100个问题搞定Java虚拟机》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和文献引用请见100个问题搞定Java虚拟机 解答 强度对比: 强引用 > ...
  • Java从JDK1.2版本开始,把对象的引用分为四种级别:强引用、软引用、弱引用和虚引用。之所以将引用分成这四种不同的类型,是为了在JVM中更加灵活的进行对象的垃圾回收,从而让程序更加灵活的控制对象的生命周期。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 452,380
精华内容 180,952
关键字:

四种java引用

java 订阅
友情链接: (3) 40626026pso.rar