WeakHashMap 的键回收完全由 JVM GC 决定:只要键无外部强引用,就可能在任意 GC(如 Minor/Full GC)中被回收;回收后 Entry 并不立即删除,需后续调用 get/size 等方法触发 expungeStaleEntries() 清理;String 字面量等常量池对象因被 JVM 强引用,基本不会被回收。

WeakHashMap 的键被垃圾回收的时机,完全由 JVM 的 GC 决定,不取决于 WeakHashMap 自身——只要键对象**没有其他强引用**,它就可能在**任意一次 GC 过程中被回收**,常见于 Minor GC 或 Full GC 阶段。
键被 GC 回收的前提条件
GC 能回收 WeakHashMap 中的键,必须同时满足以下两点:
- 外部代码不再持有该键对象的任何强引用(比如局部变量、集合、静态字段等都已脱离)
- JVM 从 GC Roots 出发进行可达性分析时,发现该键仅被 WeakReference 包装(即 WeakHashMap 内部的 Entry),无其他强路径可达
回收不是“立刻发生”,而是“随时可能发生”
WeakHashMap 不主动触发 GC,也不控制回收时间。即使你刚 put 进去一个 key,只要它立即失去所有强引用,下一次 GC 就可能把它收走。实际延迟取决于:
- 当前堆内存压力(是否触发 GC)
- GC 算法和策略(如 G1 的 Region 回收节奏、ZGC 的并发标记阶段)
- 键对象所处的代(年轻代对象可能很快被 Minor GC 回收;老年代需等待 Full GC 或混合回收)
回收后 Entry 并不会“马上消失”
键被 GC 回收后,对应 Entry 仍留在哈希表中,直到你下次调用 get、put、size、keySet 等方法——此时 WeakHashMap 会自动调用 expungeStaleEntries(),从内部 ReferenceQueue 中取出已失效的弱引用,并清理对应槽位。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
这意味着:
- get(key) 可能突然返回 null,即使你没手动 remove
- entrySet() 遍历时,next() 返回的 Entry.getKey() 可能为 null,需显式判空
- size() 返回的是当前存活 Entry 数,不是插入总数
哪些键很难被 GC?要特别避开
以下类型的对象作为 WeakHashMap 的键,基本不会被回收,因为 JVM 对它们做了强引用驻留:
- String 字面量(如 "hello")——存在字符串常量池中
- Integer、Byte、Short 等小整数值(-128 ~ 127)——缓存在 IntegerCache 等内部缓存里
- 枚举常量、Class 对象、static final 字段引用的对象
这些都不适合作为 WeakHashMap 的键,否则“弱引用”形同虚设。

















