---
title: 使能JBolt特性
description: "主流JIT编译简单按照编译时机将方法代码追加到代码缓存区中，在热方法多且分布散乱时icache/iTLB miss就会引起较高的CPU惩罚，造成前端系统瓶颈。JBolt特性利用采样手段获取运行时JIT方法的热点和调用链关系，再通过算法重排将热方法代码以较优方式集中，提高空间局部性，降低icache/iTLB miss率以提升程序性能。"
url: https://www.hikunpeng.com/document/detail/zh/kunpengaccel/system-lib/ugbishengjdklib/kunpengaccel_jdk_06_0006.html
sourcePath: /source/zh/kunpengaccel/system-lib/ugbishengjdklib/kunpengaccel_jdk_06_0006.html
indexId: 72bd29285eeb76115ceb6ac1b9ca943c6c60de2c2d66496feb16cef459babb1e80
---
# 使能JBolt特性

#### 介绍

主流JIT编译简单按照编译时机将方法代码追加到代码缓存区中，在热方法多且分布散乱时icache/iTLB miss就会引起较高的CPU惩罚，造成前端系统瓶颈。JBolt特性利用采样手段获取运行时JIT方法的热点和调用链关系，再通过算法重排将热方法代码以较优方式集中，提高空间局部性，降低icache/iTLB miss率以提升程序性能。


#### 场景建议

由JIT CodeCache引起的icache/iTLB miss率高（可使用性能分析工具跟踪CPU缓存命中率，如Linux perf命令等），应用程序热方法多且分布散乱的场景。


#### 使用约束

- 当毕昇JDK版本为11、17和21版本时支持JBolt特性，分别从毕昇JDK 11.0.27、17.0.14和21.0.7子版本后开始支持。
- 应用支持使用JFR。应用一般默认支持JFR，除非通过-XX:-FlightRecorder参数关闭此功能。
- 应用需要使能C2编译器。在-Xint及诸如AppCDS dump等不使能编译器的场景下无法使用JBolt特性。
- 应用需要支持Segmented CodeCache。JBolt依赖Java9之后的代码缓存分区特性（默认使能的），如果应用包含-XX:-TieredCompilation、-XX:-SegmentedCodeCache以及-XX:ReservedCodeCacheSize < 240M等，则会关闭这一特性，导致无法使用JBolt。
- 以下情况列出的一些软性限制，不会导致直接启动失败，但可能运行时异常或不合预期，此时也不建议使用本特性。

  - 应用Java堆内存极小的情况，开启JFR有一定内存要求，建议预先通过-XX:StartFlightRecording参数尝试是否场景可支持JFR采样，内存不够会导致使用异常。
  - 应用限制JVM模块范围的情况，如使用--limit-modules进行模块裁剪等。特性通过特权级调用完成部分自动化功能，会隐式加载部分依赖，会使得实际限制范围和预期不符。


#### （推荐）使用方法一：“一步式”模式

“一步式”模式：一次运行过程中自动完成采样及重排，可支持进行多次采样重排过程。

1. 使能JBolt，启动后自动执行一次采样重排。强烈建议添加“-Xlog:jbolt=info”参数，该参数会在JBolt各个重要环节输出信息给控制台，采样完成后自动进行重排，重排完成后加了-Xlog信息会看到“JBolt reordering succeeds.”，代表JBolt生效。此参数对“两步式”模式同样适用。命令行中spring-petclinic.jar是业务程序包举例，请结合具体使用程序进行替换。
  1 $JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+UseJBolt -Xlog:jbolt=info -jar spring-petclinic.jar

  “一步式”模式，支持如下几个参数组合使用： -XX:JBoltSampleInterval：采样持续时间（秒）。无特殊情况默认不设置，默认值600秒，即采样时间持续600秒。 -XX:JBoltCodeHeapSize：JBolt堆大小。默认值8MB，此默认值在一些编译方法较多的场景（原本使用的CodeCache偏大）可能不够用，需要结合场景设置，设置的大小需与page-size对齐，可参考值为原本实际使用的Non-profiled段大小的1/4~1/2（使用大小可用-XX:+PrintCodeCache参数查看，例：non-profiled used=16M，JBoltCodeHeapSize建议设为4M~8M之间）。 （仅JDK 11支持）-XX:JBoltRescheduling：设置每天固定时间自动采样。定义格式必须为hh:mm，多个时间使用逗号进行分隔（如：JBoltRescheduling=07:30,16:30），最多支持设置十个不重复时间（注：由于同时只能存在一个JBolt工作流程，因此如果设置的时间过近或手动采样等原因导致前一次流程未结束可能导致无法自动触发，未成功触发的时间在当天会被跳过）。

2. 在“一步式”模式下，用户可以使用jcmd命令手动控制采样时机，在线启动JBolt热点重排。
当前支持以下4个命令，使用方式参考：jcmd <pid> JBolt.xxx
<pid>为1开启的Java进程ID，结合具体业务进程在命令中替换。

  - JBolt.start：开启一次自动采样并在持续时间结束后应用重排。可选duration参数，与-XX:JBoltSampleInterval意义相同，默认值即为JBoltSampleInterval的值。使用方式：
    1 $JAVA_HOME/bin/jcmd <pid> JBolt.start [duration=<sample interval>]

    此时正在采样重排中会开启不成功，可等待时间结束或使用stop或abort命令提前结束。

  - JBolt.stop：立即停止当前采样并应用重排。使用方式：
    1 $JAVA_HOME/bin/jcmd <pid> JBolt.stop

  - JBolt.abort：与stop相同但不会应用重排。使用方式：
    1 $JAVA_HOME/bin/jcmd <pid> JBolt.abort

  - JBolt.dump：将当前应用中的顺序表导出。带一个filename必须参数指定有效文件路径。使用方式：
    1 $JAVA_HOME/bin/jcmd <pid> JBolt.dump filename=<eg: order.log>


#### 使用方法二：“两步式”模式

“两步式”模式：将采样和重排分为两个阶段分开运行。

1. 使能DumpMode，进行采样，采样持续到程序退出（需要程序自然退出或手动Ctrl+C，如果是异常退出则不会生成），将顺序表导出到指定文件。
  1 $JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+UseJBolt -XX:+JBoltDumpMode -XX:JBoltOrderFile=<eg: order.log> -Xlog:jbolt=info -jar spring-petclinic.jar

2. 使用生成的顺序表文件，再次启动程序进行布局重排应用，该步骤需要应用启动一段时间后才可能会进行重排，生效的标志与一步式下相同，生效后可期望取得优化效果。
  1 $JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+UseJBolt -XX:+JBoltLoadMode -XX:JBoltOrderFile=<eg: order.log> -Xlog:jbolt=info -jar spring-petclinic.jar

  “两步式”模式不支持jcmd命令控制采样时机的操作。
