weakHashMap与其他的map不同之处在于其key是弱引用类型,其他map的key是强引用类型。
在Java中,引用存在四种类型,分别为强引用、软引用、弱引用、虚引用
强引用
最常见的引用类型
Object o = new Object();
执行语句,变量o即为强引用
强引用指向的对象无论在何时,都不会被GC清理掉
只要强引用还存在,GC就永远不会被回收掉引用的对象,通过关键字new 创建的对象的引用就是强引用,只要这个强引用还指向某一个对象,说明对象还存活这,垃圾回收器就不会回收,当JVM内存不足,JVM宁愿抛出OutOfMemoryError运行时异常(OOM),使得程序终止,也不会随意回收强引用的”存活“对象来解决内存不足问题
java中除了强引用还存在其他三种引用,全部位于java.lang.ref包中
存在抽象的Reference类
构造函数:
//referent为引用指向的对象
Reference(T referent) {
this(referent, null);
}
//ReferenceQueue队列,简单理解是一个队列
//GC 在检测到对象引用发生改变是,要被回收是,会把引用对象添加到queue,便于清理引用对象本身
Reference(T referent, ReferenceQueue<? super T> queue) {
this.referent = referent;
this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
}
如果在创建一个引用对象时,指定了ReferenceQueue,那么当引用对象指向的对象到达合适的状态(不同引用类型状态不同),GC会把引用对象本身添加到队列,方便进行清理
软引用:SoftReference
通过软引用作用的对象会在程序即将触发OOM时被GC清理掉,之后,引用对象放入到ReferenceQueue中,
软引用用来描述一些还有用但并非必须的对象,对于软引用作用的对象,在系统将要发生内存溢出异常之前,会将这些对象列进回收范围中在此进行回收,如果回收没有足够的内存,才回去抛出内存溢出溢出异常,JDK提供了SoftReference类来实现软引用
public static void main(String[] args) {
ReferenceQueue <A> queue = new ReferenceQueue <>();
SoftReference <A> w = new SoftReference <>(new A(), queue);
System.out.println(w.get());
System.out.println(w.isEnqueued());//通过queue来判断对象有没有被回收
System.out.println(queue.poll());
/**
* com.tulun.Reference.A@560c7816
* false
* null
*/
/**
* 在内存不足时,软引用所作用的才会被回收
* -Xms:初始大小 -Xmx:最大内存大小
* -Xms10m -Xmx10m
*/
/**
* 重点
* 此处需要内存,内存不足,不够用了,因此会触发GC,回收软引用作用对象
*/
byte[] bytes = new byte[7 * 1024];
System.gc();
System.out.println("----------------");
System.out.println(w.get());
System.out.println(w.isEnqueued());//通过queue来判断对象有没有被回收
System.out.println(queue.poll());
/**
* com.tulun.Reference.A@560c7816
* false
* null
*
* 当前的程序运行软引用未被回收,为什么呢?
* 设置堆大小,限定比较小的值,当JVM在进行运行时,会有内存担保策略,额外分配空间来存储对象
*
*/
}
弱引用:weakReference
弱引用也是用来描述非必要对象,但他的强度比软引用更弱一些,被弱引用作用的对象只要发生GC操作都会回收润引用所作用的对象,一旦发生GC操作,弱引用作用的对象都会被回收
public static void main(String[] args) {
ReferenceQueue <A> queue = new ReferenceQueue <>();
WeakReference <A> w = new WeakReference<A>(new A(), queue);
System.out.println(w.get());
System.out.println(w.isEnqueued());//通过queue来判断对象有没有被回收
System.out.println(queue.poll());
/**
* com.tulun.Reference.A@20724356
* false
* null
*/
//发生GC操作
System.gc();
System.out.println("----------------");
System.out.println(w.get());
System.out.println(w.isEnqueued());//通过queue来判断对象有没有被回收
System.out.println(queue.poll());
/**
* null
* true
* java.lang.ref.WeakReference@74e7f9b3
*/
}
虚引用:PhantomReference
虚引用是最弱的一种引用关系,一个对象是否存在虚引用,完全不会对对象的生存时间构成影响,也无法通过虚引用来获取一个对象的实例,由虚引用获取的对象get永远为null,为一个对象设置虚引用关联的唯一目的是能在对象被回收时这个对象被GC回收会受到一个通知
public static void main(String[] args) {
ReferenceQueue<A> queue = new ReferenceQueue <>();
PhantomReference<A> w = new PhantomReference<A>(new A(), queue);
System.gc();
if (w.isEnqueued()) {
System.out.println("w.isEnqueued");
} else {
System.out.println("not w.isEnqueued");
}
//w.isEnqueued
}