大量内容相同的 String 能自动合并吗?哪些收集器支持?合并的是对象还是数组?阈值怎么影响什么时候发生?这篇用已用堆数字与去重线程的日志验证。
G1,不开启去重 已用堆 [28.9, 29.1, 29.1, 29.1, 29.1, 29.1, 29.1, 29.1] String 对象身份数 300000,equals 去重后 100;日志显示启用=False G1,-XX:+UseStringDeduplication 已用堆 [26.1, 10.8, 10.8, 10.8, 10.8, 10.8, 10.8, 10.8] String 对象身份数 300000,equals 去重后 100;日志显示启用=True 去重线程日志(Concurrent String Deduplication 行)累计:(批次数, 检查的 String 数, 去重的 String 数) = 300302
JDK 21 UseSerialGC 不开去重 30.2 → 30.5 MB;开去重 30.2 → 12.2 MB;日志启用=True ;去重统计 300305 JDK 21 UseParallelGC 不开去重 30.1 → 30.3 MB;开去重 30.1 → 12.0 MB;日志启用=True ;去重统计 300305 JDK 21 UseG1GC 不开去重 28.9 → 29.1 MB;开去重 26.0 → 10.8 MB;日志启用=True ;去重统计 300303 JDK 21 UseZGC 不开去重 38.0 → 40.0 MB;开去重 38.0 → 20.0 MB;日志启用=True ;去重统计 300272 JDK 21 UseShenandoahGC 不开去重 35.1 → 27.9 MB;开去重 35.1 → 9.6 MB;日志启用=True ;去重统计 300283 JDK 27 UseSerialGC 不开去重 27.0 → 27.4 MB;开去重 27.0 → 11.3 MB;日志启用=True ;去重统计 300190 JDK 27 UseParallelGC 不开去重 27.0 → 27.3 MB;开去重 27.0 → 11.3 MB;日志启用=True ;去重统计 300190 JDK 27 UseG1GC 不开去重 26.6 → 26.9 MB;开去重 25.9 → 10.9 MB;日志启用=True ;去重统计 300186 JDK 27 UseZGC 不开去重 34.0 → 36.0 MB;开去重 34.0 → 20.0 MB;日志启用=True ;去重统计 300162 JDK 27 UseShenandoahGC 不开去重 29.3 → 26.3 MB;开去重 29.5 → 10.4 MB;日志启用=True ;去重统计 300190
AgeThreshold=1 第一次大批量去重(检查 > 10 万个 String)发生在 GC(2) 之后:检查 106777 个、去重 106545 个;共 49 次年轻代 GC AgeThreshold=3 12 轮内没有出现大批量去重;共 49 次年轻代 GC AgeThreshold=10 12 轮内没有出现大批量去重;共 49 次年轻代 GC
去重之前:x == y ? false,x.equals(y) ? true
去重之后:x == y ? false,x.equals(y) ? true,hashCode 相同 ? true
intern 之后 i1 == i2 ? true