BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / java / #48181同步于 2016/3/6
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖

WeakHashMap存在强引用却被垃圾回收机制回收了

hhbb
2016/3/6镜像同步4 回复
在看Java编程思想时,有这样一个关于WeakHashMap样例代码 import java.util.WeakHashMap; class Element { private String ident; public Element(String id) { ident = id; } public String toString() { return ident; } public int hashCode() { return ident.hashCode(); } public boolean equals(Object r) { return r instanceof Element && ident.equals(((Element)r).ident); } protected void finalize() { System.out.println("Finalizing " + getClass().getSimpleName() + " " + ident); } } class Key extends Element { public Key(String id) { super(id); } } class Value extends Element { public Value(String id) { super(id); } } public class CanonicalMapping { public static void main(String[] args) { int size = 100000; // Or, choose size via the command line: if(args.length > 0) size = new Integer(args[0]); Key[] keys = new Key[size]; WeakHashMap<Key,Value> map = new WeakHashMap<Key,Value>(); for(int i = 0; i < size; i++) { Key k = new Key(Integer.toString(i)); Value v = new Value(Integer.toString(i)); if(i % 3 == 0) keys[i] = k; // Save as "real" references map.put(k, v); } System.gc(); System.gc(); System.gc(); } } 我的理解是,最后键值为3的倍数的键不应该被回收,但是执行结果里3的倍数却被回收了 是我的理解有误吗?麻烦大神指导一下
订阅后,新回复会通过你的通知中心匿名送达。
4 条回复
wbzj1110机器人#1 · 2016/3/6
java对于引用分为,强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4种,WeakHashMap弱引用,对象的生存只能到下一次GC前,也就是无论是否有强引用,最后一定会回收的。
hhbb机器人#2 · 2016/3/6
多谢啊 但是好像不是这个样子吧!Java编程思想上对WeakHashMap是这么说的 “A map of weak keys that allow objects referred to by the map to be released; designed to solve certain types of problems. If no references to a particular key are held outside the map, that key may be garbage collected. ” 【 在 wbzj1110 的大作中提到: 】 : java对于引用分为,强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4种,WeakHashMap弱引用,对象的生存只能到下一次GC前,也就是无论是否有强引用,最后一定会回收的。
nuanyangyang机器人#3 · 2016/3/6
看样子优化器太聪明了,在你调用GC的时候就已经知道你的keys数组不会再用了,所以就认为keys数组死了,然后里面所有的key都没有强引用了。泡泡我这个程序试试看。然后,把最后读取keys的那个for循环注释掉试试看。 p.s. Java并不保证在程序退出的时候所有的对象的finalize方法都会被调用。所有如果不加那些System.gc(),有可能某些对象的finalize永远不会被调用。 package cn.byr.nuanyangyang.weakmap; import java.util.WeakHashMap; class Element { private String ident; private String msg; private boolean important; public Element(String id) { ident = id; int rem = Integer.parseInt(ident) % 3; msg = String.format("Finalizing %s %s (%d)", getClass().getSimpleName(), ident, rem); important = this instanceof Key && rem == 0; } public String toString() { return ident; } public int hashCode() { return ident.hashCode(); } public boolean equals(Object r) { return r instanceof Element && ident.equals(((Element) r).ident); } protected void finalize() { if (important) { System.out.println(msg); } } } class Key extends Element { public Key(String id) { super(id); } } class Value extends Element { public Value(String id) { super(id); } } public class CanonicalMapping { public static void main(String[] args) { int size = 100000; // Or, choose size via the command line: if (args.length > 0) size = new Integer(args[0]); Key[] keys = new Key[size]; WeakHashMap<Key, Value> map = new WeakHashMap<Key, Value>(); for (int i = 0; i < size; i++) { Key k = new Key(Integer.toString(i)); Value v = new Value(Integer.toString(i)); if (i % 3 == 0) keys[i] = k; // Save as "real" references map.put(k, v); } System.gc(); System.gc(); System.gc(); System.out.println("----------------------------------- Start counting here."); int nkeys = 0; for (Key k: keys) { nkeys++; } System.out.printf("----------------------------------- nkeys=%d\n", nkeys); System.out.println("----------------------------------- Main ends here."); System.gc(); System.gc(); System.gc(); } }
hhbb机器人#4 · 2016/3/7
多谢暖神指点啊!我试着把储存键值引用的数组做为类变量时,发现却不会回收键值为3的倍数的键。应该也是由于优化器的缘故。 【 在 nuanyangyang 的大作中提到: 】 : 看样子优化器太聪明了,在你调用GC的时候就已经知道你的keys数组不会再用了,所以就认为keys数组死了,然后里面所有的key都没有强引用了。泡泡我这个程序试试看。然后,把最后读取keys的那个for循环注释掉试试看。 : p.s. Java并不保证在程序退出的时候所有的对象的finalize方法都会被调用。所有如果不加那些System.gc(),有可能某些对象的finalize永远不会被调用。 : [code=java] : ...................