
guava cache 在未显式设置 `maximumsize()` 时无硬性条目数量上限,理论最大容量为 `integer.max_value`(约 21 亿),但实际受限于 jvm 堆内存,通常在达到理论极限前就会因 oom 而失败。
当使用 CacheBuilder.newBuilder().build() 创建缓存(如 Cache
从源码与设计契约来看,Guava 的 Cache 实现(底层为 LocalCache)在未配置容量约束时,条目数量的理论上限由 Java 数组索引与内部哈希表结构决定,即 Integer.MAX_VALUE(2³¹−1 ≈ 2.147×10⁹)。但这仅是数据结构层面的数学边界,绝非可用的安全阈值。
⚠️ 实际使用中,请务必注意以下关键事实:
- 内存早于数量见顶:假设每个缓存条目平均占用 128 字节(含 String 键、轻量对象值及 LocalCache 自身节点开销),容纳 1 千万个条目即需约 1.2 GB 堆空间;1 亿条目则超 12 GB。绝大多数生产环境 JVM 难以长期稳定支撑数十 GB 缓存堆,更不用说逼近 20+ GB 的临界点。
- 无自动回收 → 内存泄漏风险极高:未配置 expireAfterWrite、expireAfterAccess 或 refreshAfterWrite,且未手动调用 invalidate() / invalidateAll(),缓存将无限增长,最终触发 OutOfMemoryError: Java heap space。
- GC 压力陡增:大量短生命周期缓存对象会加剧年轻代 GC 频率;若对象被长期持有,还会抬高老年代占用,影响整体吞吐。
✅ 正确实践建议:
-
始终显式设限:即使业务“暂无明确上限”,也应基于监控数据设定保守值,例如:
Cache
safeCache = CacheBuilder.newBuilder() .maximumSize(10_000) // 明确条目上限 .expireAfterWrite(10, TimeUnit.MINUTES) // 辅助过期保障 .recordStats() // 开启统计便于观测 .build(); -
结合权重控制更灵活:对大小差异大的值,优先使用 weigher() + maximumWeight():
Cache
blobCache = CacheBuilder.newBuilder() .maximumWeight(100_000_000) // 100 MB 总权重 .weigher((k, v) -> v.length) // 按字节数计算权重 .build(); - 监控先行:通过 cache.stats() 定期采集 hitRate()、evictionCount()、estimatedSize(),结合 JVM 堆使用率告警,实现容量治理闭环。
总之,CacheBuilder.newBuilder().build() 创建的是一个“自由但危险”的缓存——它赋予你完全控制权,也把内存安全责任全盘托付给你。在生产系统中,不设限 ≠ 无限制,而是将容量瓶颈从框架层转移到了运维与架构决策层。










