假设在jvm启动时load飙高,然后逐渐正常的情况 ,我们常常会怀疑到 JIT 编译的问题。
添加启动时编译的核心数肯定是一个有效的解决的方法,可是这个參数在启动时设置后,假设正常执行时不须要这么多核来工作。
你又不能在jvm已经启动的情况下动态减少这个參数。
所以使用-XX:+TieredCompilation进行分层编译,能够缓解这个问题,其实也有非常多case使用这个參数攻克了jvm启动时load飙高的问题。
可是。假设打开分层编译,c1,c2的编译结果会比未分层的c2结果占用更大的CodeCache,非常可能会超过默认的96m空间。
即使没有占满CodeCache,假设一次回收的空间较大,比方回收后可用空间为30m,可是每次编译的代码仅仅有几百字节到几k,那么可用空间将会严重碎片化。
更可悲的是jdk7中,维护这个可用空间的是一个链表,查询到一个特定大小的连续空间函数largest_free_block()是加锁的。用一个加锁的函数訪问一个巨大的列表,
结果可想而知。
也就是说,假设你不小心使用了jdk7的没有patch过的版本号。打开了 -XX:+TieredCompilation參数,它不但不能优化,反而会由于argest_free_block()占用掉整个cpu。
详细请看:http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8006952
之所以查到这个bug,正是我们的一个应用踩到这个雷了。应用被-XX:+TieredCompilation參数拖死。
由于是虚拟机,我们如今的解决方法是在启动时动态分配给虚拟机很多其它的内核加快JIT编译,正常启动后将虚拟机内核数恢复正常。