WeakHashMap原理疑点----望大佬一起探讨
河边放牛娃 2019-08-13 09:59:38 今天闲来无事看一看WeakHashMap的源码,结合网上文章了解到了WeakHashMap清除死键(key已经被垃圾回收)是通过expungeStaleEntries()方法实现的,而此方法的调用是在WeakHashMap的方法操作之内调用的如put、get、等,为了验证这个说法做了一个小实验,看下面这段代码:JVM配置 -Xms5m -Xmx5m 使用 jdk1.8 版本
public static void main(String[] args)throws Exception {
WeakHashMap<Object,Object> map = new WeakHashMap<>();
//INFO 1 现在for循环中分配3M
for (int i = 0; i < 3; i++) {
byte[] _1M = new byte[1024*1024];
map.put(new Object(),_1M);
}
//INFO 2 单独分配1M
//System.gc();
// Thread.sleep(10000);
byte[] alloc = new byte[1024*1024];
}
首先这段代码不论如何运行都将报OutOfMemoryError,这个不难理解在for循环中分配了3M后面单独分配1M导致内存溢出。
但是当把System.gc()注释放开情况就比较诡异了,有两点神奇之处:
1. 直接运行和断点调试结果不一样
直接运行不论运行多少次都是内存溢出错误
如果以调试方式运行,在System.gc()处打上断点,调试运行到此处放过代码将不会有内存溢出错误
我的思考:是不是人为调试模式时在System.gc处有停顿,给予了垃圾回收器回收时间使得weakHashMap中的内存被释放,基于这种思考我在System.gc()语句后加了Thread.sleep(10000)停顿10s给垃圾回收机会,然后直接运行程序仍然有内存溢出错误,到这儿我就彻底懵逼了,还望大佬解答。
2. 没有调用weakHashMap的任何操作,为什么内存被回收了?
在上面代码中,for循环后没有在进行任何的map操作,可是当调试运行到System.gc()断点处时,我查看了map的size为0,且其后的内存分配也不会导致内存溢出,那么map中的内存引用是何时被移除释放的呢?