【问题标题】:Oracle JVM 8: when Codecache flushing is enabled, how much is flushed?Oracle JVM 8:启用 Codecache 刷新时,刷新多少?
【发布时间】:2016-07-03 19:26:22
【问题描述】:

我正在运行一个启用了 ReservedCodeCacheSize=128M 和 UseCodeCacheFlushing 的 Oracle Java 8 JVM(服务器,不是客户端或嵌入式)。几天后,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%,但另一种可能的解释是上述博文不准确。

【问题讨论】:

    标签: java jvm


    【解决方案1】:

    'Older half' 并不意味着所有 nmethods 的 50%。 HotSpot 扫编译代码的逻辑有点复杂;最好的解释是它的source code,但我会在下面给出一个简短的总结。

    如果至少满足以下条件之一,则会调用清扫器:

    1. 代码缓存已满。
    2. 自上次扫描以来状态发生了足够多的变化(JDK 8 测量 '足够' 超过 ReservedCodeCacheSize 的 1%)。
    3. 自上次扫描以来已经过了一定的时间间隔。代码缓存中可用的空间越多,调用清扫器的频率就越低。确切的公式是here

    当清扫器运行时,它总是释放所有 zombie nmethods,即没有激活的卸载、反优化或重新编译的方法。

    此外,如果启用了UseCodeCacheFlushing,它会释放alive足够的n个方法。冷法确定如下:

    • 在每个安全点,具有活动堆栈帧的 nmethods 的 hotness 计数器 被重置为默认值。默认热度值为2 * (ReservedCodeCacheSize / 1MB)
    • 每次清扫器运行时,它都会将活动方法的热度计数器减 1。
    • 如果热度计数器小于计算的阈值,则释放 nmethod。阈值取决于 Code Cache free ratio 和 -XX:NmethodSweepActivity 选项(默认为 10)。 NmethodSweepActivity 越大,Code Cache free ratio 越小,对编译方法的扫描越积极。 Here 是公式。

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

    【讨论】:

    • 您提到了 OpenJDK 源代码。您认为 Oracle JVM 使用相同的算法吗?
    • @user100464 是的,OpenJDK 和 Oracle JDK 运行相同的 HotSpot JVM,只是 OpenJDK 版本的 JVM 缺少某些商业功能。
    猜你喜欢
    • 1970-01-01
    • 2022-10-31
    • 1970-01-01
    • 1970-01-01
    • 2018-04-20
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    • 2013-11-26
    相关资源
    最近更新 更多