强引用(默认支持的默认)
强引用就是我们常见的普通对象引用
/**
* 强引用
*/
private Object strongReference= new Object();
只要还有一个强引用指向一个对象,就表明对象“活着”
当内存不足 的时候,JVM开始垃圾回收,对于强引用的对象,就算是出现了OOM也不会对该对象进行回收,死也不收
强引用是造成内存泄漏的主要原因
软引用
软引用需要通过Jdk提供的 java.lang.ref.SoftReference实现
/**
* 软引用案例
*/
private static void softReference () {
Object object = new Object();
//通过SoftReference软引用对象
//当开始垃圾回收时,内存充足object不会被回收,内存不足,object被回收
SoftReference< Object > objectSoftReference = new SoftReference<>(object);
}
对于软引用的对象来说
1、当系统内存充足时它 不会 被回收
2、当系统内存不足时它 会 被回收
在高速缓存中就有软引用
弱引用
弱引用需要通过Jdk提供的 java.lang.ref.WeakReference实现
弱引用的对象,在垃圾回收的时候,无论内存是否充足,都会被垃圾回收
/**
* 弱引用案例
*/
public static void weakReference () {
Object object = new Object();
//当开始垃圾回收的时候,无论内存是否充足,弱引用的对象都会被回收
WeakReference< Object > objectWeakReference = new WeakReference<>(object);
}
软引用 、弱引用适用场景
图片缓存
假如有一个应用需要读到大量的本地图片:
~ 如果每次读取图片都要从硬盘读取则会严重影响性能
~ 如果一次性全部加载到内存中又有可能造成内存泄漏
这个软引用可以解决这个问题
设计的思路是:用一个HashMap 来保存图片的路径 和 相应图片对象 关联的软引用 之间的映射关系
内存不足时,JVM会自动回收这些缓存图片所占用的空间,避免OOM
下面我自己写了个缓存类的模板( 要看具体的业务需求 还可以使用WeakHashMap,SoftHashMap)
package com.demo.pojo;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.function.Supplier;
/**
* 缓存类
*/
public class CacheUtils {
private static volatile CacheUtils instance;
private static Map< Object, Object > cacheMap;
private CacheUtils () {
}
/**
* 根据业务不同,选择构造不同的map 如WeakHashMap ,SoftHashMap 或者其他自定义
*
* @param supplier
*/
public static Map< Object, Object > getCacheMap (Supplier< Map > supplier) {
if (cacheMap == null) {
synchronized (CacheUtils.class) {
if (cacheMap == null) {
cacheMap = supplier.get();
}
}
}
return cacheMap;
}
/**
* 通过静态内部类实现单例
*/
private static class CacheUtilsInstance {
private static final CacheUtils INSTANCE = new CacheUtils();
}
public static CacheUtils getInstance () {
return CacheUtilsInstance.INSTANCE;
}
public static void main (String[] args) {
//根据业务需求,去创建对应的缓存map
Map< Object, Object > cacheMap = CacheUtils.getInstance().getCacheMap(() -> {
return new WeakHashMap();
});
}
}
知道弱引用,那聊聊WeakHashMap
WeakHashMap就是Map的一种,底层就是将kv 用WeakReference 包装起来 ,还有和引用队列ReferenceQueue结合使用(引用队列下面 会进行介绍)
下面是它的结点的代码
/**
* The entries in this hash table extend WeakReference, using its main ref
* field as the key.
*/
private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
V value;
final int hash;
Entry<K,V> next;
/**
* Creates new entry.
*/
Entry(Object key, V value,
ReferenceQueue<Object> queue,
int hash, Entry<K,V> next) {
super(key, queue);
this.value = value;
this.hash = hash;
this.next = next;
}
虚引用
一、引用队列
了解虚引用之前,必须要了解引用队列, 虚引用需要和引用队列搭配使用
如果用了引用队列,对象在被回收前需要被引用队列保存下
public class ReferenceQueueDemo {
public static void main(String[] args) throws InterruptedException {
Object o1 = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
WeakReference<Object> weakReference = new WeakReference<>(o1, referenceQueue);
System.out.println(o1);
System.out.println(weakReference.get());
System.out.println(referenceQueue.poll());
System.out.println("--------------------------");
o1 = null;
System.gc();
Thread.sleep(500);
System.out.println(o1);
System.out.println(weakReference.get());
System.out.println(referenceQueue.poll());
}
}
软(内存不够时)、弱、虚引用,gc后放到引用队列中
java.lang.Object@1540e19d
java.lang.Object@1540e19d
null
--------------------------
null
null
java.lang.ref.WeakReference@677327b6
二、虚引用
虚引用需要 java.lang.ref.PhantomReference 来实现
顾名思义,他形同虚设,虚引用不会决定对象的生命周期
如果一个对象一个对象仅持有虚引用,在任何时候都有可能被垃圾回收器回收,而且他必须和引用队列ReferenceQueue搭配使用
public class PhantomReferenceDemo {
public static void main(String[] args) {
Object o1 = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
PhantomReference<Object> reference = new PhantomReference<>(o1, referenceQueue);
System.out.println(o1);
System.out.println(reference.get());
System.out.println(referenceQueue.poll());
o1 = null;
System.gc();
System.out.println("------------------");
System.out.println(o1);
System.out.println(reference.get());
System.out.println(referenceQueue.poll());
}
}
java.lang.Object@1540e19d
null
null
------------------
null
null
java.lang.ref.PhantomReference@677327b6