前言:
学习guavaCache的时候遇到的一些比较模糊的地方,之前复习过的,现在又忘了,写个blog记录一下下。
Java 四种引用
强引用 Strong Reference
日常开发我们锁创建的引用就是强引用。例子:Student obj=new Student();
软引用 Solf Reference
软引用是用来描述一些非必需但仍有用的对象。在内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。
Java中需要使用SoftReference来使用软引用
如果一个对象惟一剩下的引用是软引用,那么该对象是软可及的(softly reachable)。垃圾收集器并不像其收集弱可及的对象一样尽量地收集软可及的对象,相反,它只在真正 “需要” 内存时才收集软可及的对象。
弱引用 Weak Reference
弱引用的引用强度比软引用要更弱一些,无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收。在 JDK1.2 之后,用 java.lang.ref.WeakReference 来表示弱引用。
如果一个对象惟一剩下的引用是弱引用,那么该对象是软可及的(softly reachable)。垃圾收集器会尽量地收集弱可及的对象。
虚引用 Phantom Reference
虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,它随时可能会被回收,在 JDK1.2 之后,用 PhantomReference 类来表示,通过查看这个类的源码,发现它只有一个构造函数和一个 get() 方法,而且它的 get() 方法仅仅是返回一个null,也就是说将永远无法通过虚引用来获取对象,虚引用必须要和 ReferenceQueue 引用队列一起使用。
引用队列(ReferenceQueue)
引用队列可以与软引用、弱引用以及虚引用一起配合使用,当垃圾回收器准备回收一个对象时,如果发现它还有引用,那么就会在回收对象之前,把这个引用加入到与之关联的引用队列中去。程序可以通过判断引用队列中是否已经加入了引用,来判断被引用的对象是否将要被垃圾回收,这样就可以在对象被回收之前采取一些必要的措施。
各个引用类型测试代码
/**
* @Classname FourReferenceTest
* @Description 四种引用的测试 配置参数 -Xms2M -Xmx3M,将 JVM 的初始内存设为2M,最大可用内存为 3M。
* @Author lqhao
* @Date 2021/8/17 11:32
* @Version 1.0
*/
public class FourReferenceTest {
private static List<Object> list = new ArrayList<>();
private static ReferenceQueue<byte[]> rq = new ReferenceQueue<byte[]>();
private static int _1M = 1024*1024;
public static void main(String[] args) {
//测试强引用
// testStrongReference();
//测试弱引用
// testSoftReference();
//测试强引用
// testWeakReference();
//测试引用队列
testReferenceQueue();
}
private static void testStrongReference() {
// 当 new byte为 1M 时,程序运行正常
// byte[] buff = new byte[1024 * 1024 * 1];
// 当 new byte为 3M 时,程序直接报错,强引用并不会被回收
byte[] buff = new byte[_1M * 3];
}
private static void testSoftReference() {
for (int i = 0; i < 10; i++) {
byte[] buff = new byte[_1M];
SoftReference<byte[]> sr = new SoftReference<>(buff);
list.add(sr);
}
System.gc(); //主动通知垃圾回收
for(int i=0; i < list.size(); i++){
Object obj = ((SoftReference) list.get(i)).get();
System.out.println(obj);
}
}
private static void testWeakReference() {
for (int i = 0; i < 10; i++) {
byte[] buff = new byte[_1M];
WeakReference<byte[]> sr = new WeakReference<>(buff);
list.add(sr);
}
System.gc(); //主动通知垃圾回收
for(int i=0; i < list.size(); i++){
Object obj = ((WeakReference) list.get(i)).get();
System.out.println(obj);
}
}
private static void testReferenceQueue(){
Object value = new Object();
Map<Object, Object> map = new HashMap<>();
Thread thread = new Thread(() -> {
try {
int cnt = 0;
WeakReference<byte[]> k;
while((k = (WeakReference) rq.remove()) != null) {
System.out.println((cnt++) + "回收了:" + k);
}
} catch(InterruptedException e) {
//结束循环
}
});
thread.setDaemon(true);
thread.start();
for(int i = 0;i < 1000;i++) {
byte[] bytes = new byte[_1M];
WeakReference<byte[]> weakReference = new WeakReference<byte[]>(bytes, rq);
map.put(weakReference, value);
}
System.out.println("map.size->" + map.size());
}
}