g1字符串去重仅作用于堆中new创建的重复string对象,需启用-xx:+useg1gc和-xx:+usestringdedlication, 通过并发标记识别并使重复对象共享底层字符数组, 降低内存占用。该机制不影响常量池字面量, 需结合-xx:+printstringdeduplicationstatistics验证效果。 150字符。``

G1 的字符串去重(String Deduplication)功能可用于减少重复 String 对象的内存占用,但需明确:它只对堆中已存在的、内容相同但对象不同的 String 实例生效,且仅作用于通过 new String("...") 创建的字符串(即堆上新建的实例),不处理字符串常量池中的字面量。
启用字符串去重功能
需在 JVM 启动时显式开启,仅当使用 G1 垃圾回收器时有效:
-
必须启用 G1:添加
-XX:+UseG1GC -
必须启用去重:添加
-XX:+UseStringDeduplication - (可选)调整去重频率与阈值:如
-XX:StringDeduplicationAgeThreshold=3表示对象至少经历 3 次 Minor GC 后才参与去重,默认为 3;-XX:+PrintStringDeduplicationStatistics可输出去重统计日志
去重机制如何工作
G1 在并发标记阶段扫描存活的 String 对象,对满足条件的实例(字符数组内容相同、未被去重过、年龄达标)执行以下操作:
- 保留其中一个实例的底层
char[](或byte[],Java 9+ 使用压缩字符串) - 让其他重复的
String对象共享该数组引用,原各自持有的数组被标记为可回收 - 去重过程是线程安全的,由 G1 并发执行,不影响应用线程停顿时间
实际效果与注意事项
去重效果高度依赖应用行为:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 适合大量通过
new String(jsonStr)、new String(bytes, "UTF-8")等方式创建重复字符串的场景(如解析 JSON、HTTP 响应体) -
对字符串字面量(如
"hello")无效:它们位于运行时常量池,由 JVM 自动管理,不参与 G1 去重 - 去重不改变字符串语义:所有去重后的
String仍保持equals()和hashCode()正确性 - 会略微增加 GC 并发线程负载,但通常开销可控;若观察到
StringDeduplication日志中“Skipped”数量高,说明多数字符串未达年龄阈值或已被 intern
验证是否生效
添加以下 JVM 参数后,观察 GC 日志:
-XX:+PrintStringDeduplicationStatistics-
-Xlog:gc+stringdedup=debug(JDK 10+,推荐)或-XX:+PrintGCDetails(旧版)
正常运行后,日志中会出现类似:
[String Deduplication: 2422K->156K(2266K), 0.0022125 secs]其中 2422K->156K 表示去重前字符数组总大小为 2422KB,去重后仅保留 156KB,释放约 2266KB 内存。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










