Oracle JVM 8:启用Codecache刷新时,刷新了多少?

时间:2016-07-03 19:26:23

标签: java jvm

我正在运行Oracle Java 8 JVM(服务器,而不是客户端或嵌入式),启用了ReservedCodeCacheSize = 128M和UseCodeCacheFlushing。几天之后,Codecache迅速从93%降至80%。我假设我目睹了一个Codecache同花顺,但令人惊讶的是,后冲洗大小接近100%满,而不是50%满。

JVM如何决定要刷新多少Codecache?

This Oracle Java 8 page描述了该选项,但没有量化刷新的Codecache:

  

在关闭编译器之前启用刷新代码缓存。默认情况下启用此选项。要在关闭编译器之前禁用刷新代码缓存,请指定-XX:-UseCodeCacheFlushing。

This Oracle blog post说,

  

有一个JVM选项UseCodeCacheFlushing可用于控制Codecache的刷新。启用此选项后,JVM将调用紧急刷新,丢弃旧版本的一半编译代码(nmethods),以便在CodeCache中提供空间。

可以想象,编译代码的旧版本只占整个Codecache的20%,但另一种可能的解释是上述博客文章不准确。

1 个答案:

答案 0 :(得分:5)

'较旧的一半'并不意味着所有nmethods的50%。用于扫描编译代码的HotSpot逻辑有点复杂;最好的解释是source code,但我将在下面给出一个简短的摘要。

如果满足以下条件中的至少一个,则调用sweeper:

  1. 代码缓存已满。
  2. 自上次扫描以来有足够的状态更改(JDK 8测量'够'超过ReservedCodeCacheSize的1%)。
  3. 自上次扫描以来已经过了一定的间隔。代码高速缓存中可用的空间越多,调用扫描器的频率就越低。确切的公式为here
  4. 当清扫程序运行时,它总是释放所有 zombie nmethods,即没有激活的卸载,去优化或重新编译的方法。

    此外,如果启用了UseCodeCacheFlushing,它会释放 cold cold 的nmethods。冷方法确定如下:

    • 在每个安全点处,具有活动堆栈帧的nmethod的热度计数器将重置为默认值。默认的热度值为2 * (ReservedCodeCacheSize / 1MB)
    • 每次清扫车运行时,它会将活动方法的热度计数器减1。
    • 如果热度计数器小于计算阈值,则释放nmethod。阈值取决于代码缓存自由比率和-XX:NmethodSweepActivity选项(默认为10)。较大的是NmethodSweepActivity,代码缓存自由比率越小,编译的方法就越苛刻。 Here就是公式。

    因此,没有确切的数字可以编写多少编译方法。这是在运行时计算的,具体取决于保留的代码缓存大小,可用空间量,僵尸方法的数量,冷方法的数量以及NmethodSweepActivity等JIT人体工程学选项。