JVM编译时间与代码缓存

时间:2018-07-13 00:36:26

标签: java jvm jit jvm-codecache

我一直在对我的应用进行基准测试,并使用JMC对其进行分析。我注意到在负载下,它会执行大量的JIT编译。如果我每秒发送大量事务,则编译时间会增加。在针对该应用程序进行任何重负载测试时,编译时间始终会按比例增长。

我还观察到代码缓存也缓慢上升。因此,我决定将代码缓存的保留空间提高到500MB进行测试。不好的举动!现在,它花费更多的时间执行JIT。

然后,我通过-XX:-UseCodeCacheFlushing明确禁用了代码缓存刷新。但是,我注意到峰值代码缓存使用率大于当前大小。这使我想到了两个问题:

FieldMask definition itself

  1. JVM是否尝试缓存每个JIT编译?
  2. 即使禁用了刷新,为什么峰值代码缓存大小也大于当前大小?
  3. 函数结束后是否有自动删除的“临时”编译代码?

1 个答案:

答案 0 :(得分:2)

在HotSpot JVM中,所有JIT编译的方法都将保留在CodeCache中,直到它们被回收为止。 UseCodeCacheFlushing影响冷(但仍然有效)编译方法的回收。但是,CodeCache也可能包含过时或无效的方法(“僵尸”),即使使用-XX:-UseCodeCacheFlushing,这些方法也可能在下一个扫描周期中清除。

  • tiered compilation模式下(自JDK 8起为默认模式),可以使用不同级别的优化将方法多次编译。一旦安装了方法的优化(第4层)版本,以前的版本就会过时,并且可以在该版本的所有激活完成后回收。
  • 当推测失败时(例如,在加载新类之后),推测性编译的方法可能变得无效。这种方法也变成僵尸,以后可以回收。
  • 另一个示例是OSR compilation。这是方法的版本,专门为在方法运行时将执行从解释器传输到已编译的代码而编译。回答您的第三个问题,这是一种“临时”方法,在安装了完整版的已编译方法并完成所有OSR激活后,该方法已过时。

有一个单独的JVM标志-XX:-MethodFlushing,可防止包括僵尸方法在内的所有代码缓存被完全清除。