此篇介绍下java中四种引用的用法与使用场景。上一篇讲到了ThreadLocal,就有用到弱引用哦。
强引用 定义强引用就是我们在java中普通使用的引用。当该类型的引用指向一个对象的时候,对象就不会被垃圾回收器进行回收。
实验代码新建一个类M,重写回收方法,该方法会在对象被垃圾回收时调用。main线程中new 出M,手动调用垃圾回收方法,将引用设置null和不设置,分别查看运行结果。
public class M {
@Override
protected void finalize() throws Throwable {
System.out.println("finalize");
}
}
public class T01_NormalReference {
public static void main(String[] args) throws IOException {
M m = new M();
// m = null;
System.gc();
System.in.read();
}
}
软引用
当gc时不一定会被回收,当JVM内存不够的时候,会将其进行回收,非常适合用于缓存。
实验代码该实验的前提,把jvm的堆内存分配<25M。
//软引用非常适合缓存使用
public class T02_SoftReference {
public static void main(String[] args) {
SoftReference<byte[]> m = new SoftReference<>(new byte[1024*1024*10]);
//m = null;
System.out.println(m.get());
System.gc();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(m.get());
//再分配一个数组,heap将装不下,这时候系统会垃圾回收,先回收一次,如果不够,会 //把软引用干掉
byte[] b = new byte[1024*1024*15];
System.out.println(m.get());
}
}
弱引用
当gc时一定会被回收。回顾上一篇讲到的ThreadLocal,我们知道,线程中有一个独有的Map,key是指向ThreadLocal的。这里我们考虑一个场景,当new出ThreadLocal时,有指向其的局部变量tl,并set给了一个线程,当方法执行完时,tl会消失。正常ThreadLocal对象会被回收,可是由于线程内map的key指向了它,导致其不能被回收,而其也无法被访问到。这样就会造成内存泄漏,所以线程中threadLocals的key实际就是弱引用。
虚引用虚引用是用来管理堆外内存的,它会指向一个堆外内存,并关联一个队列。当堆外内存被回收时,会将其放入一个队列,从而通知JVM执行相应的 *** 作。主要是在JVM开发中使用,这里就不做扩展了。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)