WeakHashMap,顾名思义是一个有弱引用的HashMap,关于弱引用对象,大家知道的应该是只要进行垃圾回收,此对象也会随之被回收,而WeakHashMap中的弱引用对象是它的静态内部类存储键值对的Entry所实现的。
在测试WeakHashMap中的弱引用对象被回收的过程中我对JVM内存结构和垃圾回收有了进一步认知。
我们加VM参数 -XX:+PrintCommandLineFlags,打印Java默认设置,可以看出垃圾回收参数是-XX:+UseParallelGC,参考相关资料如下,看得出Parallel Scavenge和Parallel Old回收整块区域,不会产生内存碎片。
①使用有强引用的普通对象作为键,为了更清晰地感知结果,我们手动执行System.gc(),结果发现不会被回收:
②使用无引用的普通对象作为键,发现可以被回收,由此可见WeakHashMap中的虚引用是有效的:
*********************************************************************************************************************
但是我发现使用Integer和String会产生出乎意料的效果,我们加上打印GC日志参数以及将最大堆内存调整一下 。
在进行正式测试前,先说第一个小问题,如下所示,明明放进去40000个数,结果只有三万多,之前没有打印GC日志一直没想明白,后来才发现在这里int作为键后会自动装箱变成new Integer(i),从而成为一个没有强引用的对象,然后进行了Minor GC导致部分对象被回收。
第二个小问题就是将for循环中引用改为Integer类型,进行Minor GC后没有对象被回收,而将键用new Integer()包装后则又能被回收。这是因为new Integer(i)是一个没有强引用的对象,和上面问题中直接用int作为键的效果一样。
下面我们直接看GC后的map大小:
①使用整型对象作为键,发现最后剩下256,这是因为Integer中-128到127缓存在常量池里,所以不会被回收:
②使用字符串作为键,结果如下,由此也可以看出常量池中的对象不会被回收:
以上就是我对弱引用的一些见解,希望大家提出宝贵意见啊。。。