上一期中我们介绍了intern()方法的定义和它在不同JDK版本中的实现。String 的intern()方法能将我们创建的字符串维护到缓存池中,当需要使用的时候就会从缓存池中获取。
听起来很不错是吧?但实际使用起来不是那么美好。
在上期我们提到:jdk6和jdk7中缓存池在JVM中的位置是不一样的。在jdk6中,缓存池是存放在方法区的“永久代”中的,而在jdk7以后,缓存池被放置在了堆内存中。
而方法区中的“永久代”空间是有限的,而且也基本不会被FullGC之外的垃圾收集器照顾到。如果intern()方法在jdk中被大量使用,那缓存池很快就会被占满,从而引发OOM异常。因此在jdk6中,不推荐大量使用intern()方法。
在jdk7后,缓存池被放置到了堆内存中,这样就极大地避免了缓存池被占满的情况。但是一旦缓存池中的字符串达到一定规模后,性能就会急剧下降,因此默认的缓存池大小也在不断的扩大中,从最初的1009到7u40的60013,。我们可以使用如下两个参数打印和修改缓存池的大小。
-XX:+PrintStringTableStatistics
-XX:StringTableSize=N
Intern()方法是一种显示的排重机制,何为显示的?即需要开发者写代码时明确调用。这样就会带来两个问题:
1、使用不方便,每次写代码时都要记得去调用。
2、很难保证缓存池的效率,因此缓存池有大小限制,在代码中大量调用的话可能反而会影响整个系统的性能。
当然jdk官方也注意到了这个问题,因此在Oracle JDK 8u20后推出了一个新特性,即G1 GC下的字符串排重。这个特性是针对JVM底层进行了修改,java类型并不需要做任何改动。
不过这个功能目前是默认关闭的,需要在指定使用G1 GC的前提下,使用如下参数打开:
-XX:+UseStringDeduplication
至此,String的缓存机制我们就全部介绍完了,相信经过大家的思考,能进一步地理解String的缓存机制。
页面更新:2024-04-18
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号