Loading... # java的四种引用方式 ## 强引用(NormalReference) ```Person p = new Person();```由栈中的一个变量直接指向堆内一个对象的方式就是强引用,也是最常使用的方式,该引用的特点是,只要该对象存在引用,那么他就不会被GC回收。 ## 软引用(SoftReference) ```SoftReference<Person> p = new SoftReference<>(new Person());```p是直接指向SoftReference对象,然后SoftReference对象由一个软引用指向Person对象。软引用对象会在系统将要发生内存溢出异常之前,列入回收范围,进行二次回收,如果回收之后还是没有足够的内存才会抛出内存溢出,也就是说,软引用在内存不足时就会被回收。软引用非常适合缓存使用。 ## 弱引用(WeakReference) ```WeakReference<Person> p = new WeakReference<>(new Person());```弱引用只要遭遇到GC就会被回收,常用于容器中对象的引用例如:WeakHashMap,在ThreadLocal中,ThreadLocalMap中的key就是弱引用,这个key就是ThreadLocal对象本身,在运行时,由我们创建的ThreadLocal类型的局部变量指向它,方法结束时ThreadLocal变量被销毁,这时理应回收该ThreadLocal对象,但如果该线程长期存在,ThreadLocalMap并不会被销毁,它的key仍然指向这个ThreadLocal对象,造成内存泄漏,如果是弱引用,当ThreadLocal变量被销毁后,没有强引用指向ThreadLocal对象,弱引用遭遇GC直接被回收,看似没毛病,但实际上就算是弱引用,ThreadLocal依然会内存泄漏,ThreadLocal对象被回收key的值会变为null,从而导致key对应的整个value无法被访问,依然会内存泄漏,因此,用完ThreadLocal最好调用一下```ThreadLocal.remove()```方法。 ## 虚引用(PhantomReference) ``` ReferenceQueue<M> QUEUE = new ReferenceQueue<>(); PhantomReference<Person> p = new PhantomReference<>(new Person(), QUEUE); ``` 虚引用的构造方法要求必须传入一个队列。虚引用,顾名思义,就是一个虚幻的引用,无法通过虚引用来得到对象实例。只存在虚引用的时候,对象遭遇GC就会被回收,同时,系统会收到一个通知(QUEUE里会put进去一个对象),那么虚引用有什么作用呢。它的作用不是针对于API调用者,而是针对框架或者虚拟机开发者,虚引用一般用于对直接内存的管理,JVM自动内存管理的范围是堆内存,而直接内存属于堆外内存,一般直接内存的分配和回收都是由UNSafe类去完成的,类似C语言的malloc和free,GC是无法完成的。java申请完直接内存后,会在堆内创建一个对象保存这个堆外内存的引用,一旦这个对象被回收,用户线程就会收到通知,再手动去实现堆外内存的清理工作。设置虚引用关联的唯一目的就是能在这个对象被GC回收时收到一个系统通知。 Last modification:June 11th, 2020 at 06:08 pm © 允许规范转载