环境 java1.8 update 20 以上(我用的是java1.8.0_241)
参数
-Xms10M -Xmx10M -XX:+UseStringDeduplication -XX:+UseG1GC -XX:+PrintGCDetails -XX:+PrintStringDeduplicationStatistics
必须参数只有-XX:+UseStringDeduplication -XX:+UseG1GC这两项
但是为了加速gc达到 UseStringDeduplication 的效果我们调小了jvm最大和初始内存
再加上-XX:+PrintGCDetails -XX:+PrintStringDeduplicationStatistics 把gc日志打印出来
下面是代码,用反射把String类里面的private修饰的value拿出来,并打印内存地址
public class StringDeduplication {
public static void main(String[] args) {
String str1 = new String(new char[]{'a'});
String str2 = new String(new char[]{'a'});
Class<String> stringClass = String.class;
try {
Field value = stringClass.getDeclaredField("value");
value.setAccessible(true);
List<String> list = new ArrayList<>();
list.add(str1);
list.add(str2);
while (true) {
list.add("a");
list.remove(2);
System.out.println(value.get(str1));
System.out.println(value.get(str2));
if (value.get(str1) == value.get(str2)) {
System.out.println("StringDeduplication");
}
}
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
在
System.out.println("StringDeduplication");
这一行打一个断点,进入断点时日志如下
可以看到一开始两个value的内存地址是不一致的,再执行了gc后触发了UseStringDeduplication
这时再放开断点,两个value的内存地址就一致了,证明了UseStringDeduplication的确产生了效果,如下图: