由于String在Java中(像其他语言一样)消耗大量内存,因为每个字符占用两个字节,Java 8引入了一个名为String Deduplication的新功能,它利用了char数组是字符串内部的最终事实,因此JVM可以搞砸他们.
到目前为止,我已经阅读了这个例子,但由于我不是一个专业的java编码器,我很难掌握这个概念.
这是它说的,
已经考虑了各种字符串复制策略,但现在实现的策略遵循以下方法:每当垃圾收集器访问String对象时,它会记录char数组.它接受它们的哈希值并将其与对数组的弱引用一起存储.一旦找到另一个具有相同哈希码的String,就会将它们与char进行比较.如果它们匹配,则将修改一个String并指向第二个String的char数组.然后不再引用第一个char数组,并且可以进行垃圾回收.
整个过程当然会带来一些开销,但是受到严格的限制.例如,如果找不到字符串有一段时间的重复项,则不再检查它.
我的第一个问题,
由于最近在Java 8更新20中添加了这个主题,因此仍然缺乏资源,这里是否有人可以分享一些关于如何帮助减少StringJava 消耗内存的实际示例?
编辑:
上面的链接说,
一旦找到另一个具有相同哈希码的String,就会将它们与char进行比较
我的第二个问题,
如果两个哈希码String相同,则Strings已经是相同的,那么为什么对它们进行比较char的char,一旦发现,这两个String具有相同的散列码?
我的服务器在CentOS 6.7上使用1.8.0_92,GC参数是'-Xms16g -Xmx16g -XX:+ UseG1GC'.所以默认的InitiatingHeapOccupancyPercent是45,G1HeapWastePercent是5,而G1MixedGCLiveThresholdPercent是85.我的服务器的混合GC从7.2GB开始,但它越来越少,最后老一代保持大于7.2GB,所以它总是尝试做并发标记.最后所有堆都耗尽并且发生了完整的GC.完全GC后,使用的旧版本低于500MB.
我很好奇为什么我的混合GC不能收集更多,看起来像实时数据不是那么多......
我曾尝试打印g1相关信息,并发现许多消息如下,看起来我的旧版包含很多实时数据,但为什么完整的GC可以收集这么多......
G1Ergonomics (Mixed GCs) do not continue mixed GCs, reason: reclaimable percentage not over threshold, candidate old regions: 190 regions, reclaimable: 856223240 bytes (4.98 %), threshold: 5.00 %
Run Code Online (Sandbox Code Playgroud)
以下日志是将InitiatingHeapOccupancyPercent修改为15(启动并发标记为2.4GB)以加快速度的结果.
### PHASE Post-Marking
......
### SUMMARY capacity: 16384.00 MB used: 2918.42 MB / 17.81 % prev-live: 2407.92 MB / 14.70 % next-live: 2395.00 MB / 14.62 % remset: 56.66 MB code-roots: 0.91 MB
### PHASE Post-Sorting
....
### SUMMARY capacity: 1624.00 MB used: 1624.00 MB …Run Code Online (Sandbox Code Playgroud)