JVM优化

优化的问题1、如果YGC  随着时间的推移,耗时越来越大

      先学习一下YGC经历哪些步骤,哪些步骤会比较耗时

            步骤1   查找GC-ROOT对象,copy到to区域

            步骤2、递归步骤1,查找GC-ROOT引用的对象,copy到to区域

GC-ROOT包含的                        

  • Universe类中所引用的一些必须存活的对象 
  • 所有JNI Handles JNIHandles
  • 所有线程的栈
  • 所有被Synchronize锁持有的对象
  • VM内实现的MBean所持有的对象
  • JVMTI所持有的对象
  • (可选)所有已加载的类 或 所有已加载的系统类
  • (可选)所有驻留字符串(StringTable)
  • (可选)代码缓存(CodeCache)
  • (可选)PermGen的remember set所记录的存在跨代引用的区域

老年代引用新生代的对象情况           对象晋升为老年代时,如果还引用,此时就标记为dirty

这样YGC 不需要扫描所有的老年代,只需要扫描dirty区域

 

如果发现YGC时间变长,这时候看下老年代的大小变化情况,如果多出几百兆的时候,预判是否是老年代引用新生代的扫描时间变长,这时可以进行一次jmap -histo:live <pid>   。如果老年代降下来了,并且YGC时长变短了,则基本上就是预判的正确性。

 

YGC过程的GCRoots 里包括了 StringTable,SystemDictionary 等,这几个表的 update 在 CMS GC 或者 Full GC 的时候才有机会进行清理,如果这些表里指向的 Dead Object 比较多,那可能会导致 YGC 扫描时间比较长。

我们切换了 alijdk,加了参数 -XX:+PrintGCRootsTraceTime ,打印了下 GC 分布时间,看到 stringtable 对比刚启动的时候明显增高,之后排查代码,发现只有 Json 那个地方有用到 String 转换,使用 Jackson readValue 触发的 String.intern(),导致jvm stringtable 膨胀。

 

如果是oracle 或者hotspot的jvm,则使用java -jar -Xms1024m -XX:+PrintStringTableStatistics -XX:+PrintStringTableStatistics home.cloud.one-1.0-SNAPSHOT.jar

jvm退出时候,就可以查看这个统计;遗憾的是,只能退出时候才能看到此统计信息

既然StringTable是Hashtable数据结构,那为什么不能自己通过rehash扩大bucket数量来提高性能呢?JVM中StringTable的rehash有点不一样, JVM中StringTable的rehash不会扩大bucket数量,而是在bucket不变的前提下,通过一个新的seed尝试摊平每个bucket中LinkedList的长度(想想也是,如果StringTable能通过rehash扩大bucket数量,那还要StringTableSize干嘛),rehash大概是一个如下图所示的过程,rehash前后bucket数量不变

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值