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中的内存引用是何时被移除释放的呢?



...全文
164 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
立刀流 2019-08-14
  • 打赏
  • 举报
回复
关于第一个问题,我这儿也用你的代码尝试了,断点情况下确实会回收,非断点情况下不会回收。但是,在非断点下,在调用了gc方法后调用一下map,就会触发gc回收,后面不会报错。我也很迷 第二点,我在gc方法处打断点,map是有值的,size不为0
河边放牛娃 2019-08-13
  • 打赏
  • 举报
回复
自顶啊,欢迎各位一起探讨

51,409

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧