JVM 配置 #
本页介绍 config/jvm.options 文件中的 JVM 启动参数。这些参数在 Easysearch 启动时由 JVM 读取,修改后需要重启节点生效。
Easysearch 2.5.0 默认使用并推荐 JDK 25,Bundle 包默认内置 JDK 25。 JDK 21 仅用于兼容已部署且暂不方便升级 JDK 的客户环境;两种运行时均使用安全 agent,并要求禁用 JDK SecurityManager。 请以目标发行包的默认配置为基础调整参数。下文保留的旧 JDK 版本条件仅用于解释配置语法和历史配置,不代表当前版本支持这些运行时。
堆内存设置 #
堆内存是 JVM 配置中最重要的参数。
# 堆大小设为物理内存的 50%,但不超过 31 GB
# -Xms 和 -Xmx 必须相同,避免运行时堆调整
-Xms16g
-Xmx16g
| 参数 | 说明 |
|---|---|
-Xms | JVM 初始堆大小 |
-Xmx | JVM 最大堆大小 |
设置原则 #
-Xms和-Xmx设为相同值:避免运行时堆大小调整带来的性能波动。- 不超过物理内存的 50%:剩余内存留给操作系统文件缓存(Lucene 严重依赖 OS 页面缓存)。
- 不超过 31 GB(建议设为
31g或30g):超过约 32 GB 后 JVM 无法使用压缩对象指针(Compressed OOPs),实际可用内存反而减少。 - 不低于 1 GB:过小的堆会导致频繁 GC。
验证压缩指针 #
GET _nodes/stats/jvm?filter_path=**.using_compressed_ordinary_object_pointers
返回 true 表示压缩指针生效。
通过环境变量覆盖 #
如果不想修改 jvm.options 文件,可以通过环境变量覆盖:
ES_JAVA_OPTS="-Xms4g -Xmx4g" ./bin/easysearch
环境变量的优先级高于
jvm.options文件中的设置。
垃圾回收器 #
Easysearch 2.5.0 在默认 JDK 25 和兼容运行时 JDK 21 上均使用 G1GC。发行配置中还保留以下版本条件:
- JDK 8-10:使用 CMS(Concurrent Mark-Sweep)
- JDK 11+:默认使用 G1GC
# JDK 8-10: CMS 垃圾回收器
8-10:-XX:+UseConcMarkSweepGC
8-10:-XX:CMSInitiatingOccupancyFraction=75
8-10:-XX:+UseCMSInitiatingOccupancyOnly
# JDK 11+: G1GC(推荐)
11-:-XX:+UseG1GC
11-:-XX:G1ReservePercent=25
11-:-XX:InitiatingHeapOccupancyPercent=30
| 参数 | 说明 |
|---|---|
8-10:-XX:+UseConcMarkSweepGC | JDK 8-10 使用 CMS 垃圾回收器 |
8-10:-XX:CMSInitiatingOccupancyFraction=75 | JDK 8-10:老年代占用 75% 时触发 CMS 回收 |
11-:-XX:+UseG1GC | JDK 11+ 使用 G1GC,支持更大的堆和更稳定的暂停时间 |
11-:-XX:G1ReservePercent=25 | G1GC 预留 25% 堆用于浮动垃圾 |
11-:-XX:InitiatingHeapOccupancyPercent=30 | 堆占用 30% 时启动并发回收 |
⚠️ 注意:版本号前缀(如
8-10:、11-)表示该参数仅在指定 JDK 版本范围内生效。除非有充分的理由和测试数据,不建议更改默认 GC 配置。
OOM 保护 #
# 发生 OutOfMemoryError 时生成堆转储文件
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=data
# 发生 OOM 时的错误日志路径
-XX:ErrorFile=logs/hs_err_pid%p.log
Lucene 性能优化(JDK 9+) #
# JDK 9+:启用 Lucene 性能优化模块
# jdk.unsupported:提供 sun.misc.Unsafe 用于低级内存操作
# jdk.management:提供扩展的管理接口
9-:--add-modules=jdk.unsupported,jdk.management
Vector API 支持(JDK 20+) #
# JDK 20+:启用向量 API(孵化功能)用于 SIMD 支持
20-:--add-modules=jdk.incubator.vector
Vector API 可以加速搜索和 Lucene 索引操作,特别是在向量搜索场景中。
OOM 保护(旧语法) #
# 发生 OutOfMemoryError 时生成堆转储文件
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=data
# 发生 OOM 时立即退出 JVM(让进程管理器自动重启)
-XX:+ExitOnOutOfMemoryError
| 参数 | 说明 |
|---|---|
-XX:+HeapDumpOnOutOfMemoryError | OOM 时自动生成 heap dump 文件,用于事后分析 |
-XX:HeapDumpPath | Heap dump 文件的存储路径(相对于 $ES_HOME) |
-XX:+ExitOnOutOfMemoryError | OOM 时立即退出 JVM,而不是挂起 |
GC 日志 #
Easysearch 默认启用 GC 日志,不同 JDK 版本的配置方式不同:
JDK 8 GC 日志 #
8:-XX:+PrintGCDetails
8:-XX:+PrintGCDateStamps
8:-XX:+PrintTenuringDistribution
8:-XX:+PrintGCApplicationStoppedTime
8:-Xloggc:logs/gc.log
8:-XX:+UseGCLogFileRotation
8:-XX:NumberOfGCLogFiles=32
8:-XX:GCLogFileSize=64m
JDK 9+ GC 日志 #
9-:-Xlog:gc*,gc+age=trace,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m
| 参数部分 | 说明 |
|---|---|
gc*,gc+age=trace,safepoint | 记录 GC 事件、年龄分布、安全点 |
file=logs/gc.log | 输出到 logs/gc.log |
utctime,pid,tags | 日志中包含 UTC 时间、进程 ID、标签 |
filecount=32,filesize=64m | 最多 32 个轮转文件,每个 64 MB |
GC 日志对排查性能问题非常重要,建议保持默认开启。
其他常用 JVM 参数 #
临时目录 #
# 临时文件目录
-Djava.io.tmpdir=${ES_TMPDIR}
安全检查(默认 JDK 25,兼容 JDK 21) #
# Easysearch 2.5.0;其他发行版本使用对应包内的实际文件名
-Djava.security.manager=disallow
21:-javaagent:lib/easysearch-security-agent-2.5.0.jar
25:-javaagent:lib/easysearch-security-agent-2.5.0.jar
默认 JDK 25 和兼容运行时 JDK 21 加载同一个 Java agent 执行安全检查。
两种运行时均通过 java.security.manager=disallow 禁用 JDK 自身的 SecurityManager;
启动时会显式校验没有安装 JDK SecurityManager,且 java.security.manager 的值严格为 disallow。
缺少该参数、将其改为其他值,或已安装 JDK SecurityManager,都会拒绝启动;JDK 25 也必须保留该参数。
请保留发行包生成的 agent 参数及相邻的 bootstrap jar;缺少 agent 时服务会拒绝启动。
升级并保留旧 jvm.options 时,必须同步新发行包的 agent 文件名和必要参数,同时保留自己的堆大小等设置。
两种运行时都应保留发行配置中的 21-:--enable-preview 和 19-:--enable-native-access=ALL-UNNAMED;
JDK 21 需要这些参数来加载相应的 Lucene 和 custom-codecs 实现。
这些版本配置不代表 JDK 22~24 或 JDK 26 已受支持。
easysearch.yml 中的 security.enabled 控制认证与 TLS 等安全模块功能,不用于关闭 JVM 安全 agent 或上述启动校验。
agent 读取核心策略和 plugin-security.policy,结合配置目录、数据目录等动态权限,
检查选定的文件操作、Socket/SocketChannel 连接及 System.exit/Runtime.halt 调用。
这些检查不覆盖所有文件或网络 API,也不复刻旧 SecurityManager 的反射、线程组或异步权限上下文。
插件安装时会标明已跳过的权限类型;声明这些权限不代表相应操作仍受强制检查。
第三方插件仍需作为可信代码管理。
Locale 配置 #
# JDK 9-20:使用 SPI 和系统兼容性 Provider
9-20:-Djava.locale.providers=SPI,COMPAT
# JDK 21+:使用 SPI 和 CLDR Provider
21-:-Djava.locale.providers=SPI,CLDR
编译优化(JDK 23+) #
# JDK 23:修复 MethodHandle 性能问题
23:-XX:CompileCommand=dontinline,java/lang/invoke/MethodHandle.setAsTypeCache
23:-XX:CompileCommand=dontinline,java/lang/invoke/MethodHandle.asTypeUncached
Native Access(JDK 19+) #
# JDK 19+:为所有未命名模块启用原生访问
19-:--enable-native-access=ALL-UNNAMED
# JDK 22+:禁用向量 API 警告
22-:-Djdk.incubator.vector.disableWarnings=true
| 参数 | 说明 |
|---|---|
-Djava.io.tmpdir | JVM 临时文件目录 |
-javaagent | JDK 21、JDK 25 加载发行包提供的安全 agent |
-Djava.security.manager=disallow | 禁用 JDK 自身的 SecurityManager |
-Djava.locale.providers | JVM 使用的 Locale 提供者 |
TLS 原生库加载(Linux/macOS) #
在 Linux/macOS 的 x86_64、ARM64 平台上,启动脚本会从安全模块的 tongsuo-openjdk-*.jar 中提取当前平台的
Conscrypt 原生库到 $ES_HOME/modules/security/native/,供 TLS 加载;目标文件已存在时复用。
首次提取时,启动用户需能创建并写入该目录,所选 JDK 也必须包含 jar 工具。
jvm.options 文件格式 #
jvm.options 文件中每行一个 JVM 参数,支持版本条件:
# 这是注释
# 无条件参数(所有 JVM 版本生效)
-Xms16g
-Xmx16g
# 版本条件参数
# JDK 8~10
8-10:-XX:+UseConcMarkSweepGC
# JDK 11+
11-:-XX:+UseG1GC
# JDK 9~20
9-20:-Djava.locale.providers=SPI,COMPAT
# JDK 21+
21-:-Djava.locale.providers=SPI,CLDR
版本条件语法 #
| 格式 | 说明 | 示例 |
|---|---|---|
| 无前缀 | 所有版本生效 | -Xms16g |
N | 仅 JDK N 生效 | 25:-javaagent:lib/easysearch-security-agent-2.5.0.jar |
N- | JDK N 及以上版本 | 11-:-XX:+UseG1GC (JDK 11+) |
N-M | JDK N 到 M 版本 | 8-10:-XX:+UseConcMarkSweepGC (JDK 8-10) |
- 以
#开头的行是注释。 - 注释应单独占一行,不要放在 JVM 参数末尾。
- 空行会被忽略。
jvm.options.d 目录 #
除了主 jvm.options 文件外,Easysearch 还会读取 config/jvm.options.d/ 目录下所有以 .options 结尾的文件。每个文件的格式与主 jvm.options 完全相同。
使用场景 #
- 自定义参数与默认参数分离:将自定义 JVM 参数放在独立文件中,避免修改默认的
jvm.options文件,便于升级时保留定制配置 - 容器化部署:通过挂载配置文件到
jvm.options.d/目录,在不修改镜像的情况下调整 JVM 参数 - 按关注点组织:将不同类型的参数(如 GC、调试、安全)放在不同文件中
示例 #
创建自定义堆内存配置:
# config/jvm.options.d/heap.options
-Xms16g
-Xmx16g
创建调试参数文件:
# config/jvm.options.d/debug.options
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/log/easysearch
-XX:ErrorFile=/var/log/easysearch/hs_err_pid%p.log
加载顺序 #
- 先读取
config/jvm.options主文件 - 再按文件名字母顺序读取
config/jvm.options.d/*.options - 如果同一参数出现多次,后加载的值会覆盖先加载的值
注意:
jvm.options.d/目录中的文件必须以.options为扩展名,其他文件会被忽略。
配置示例 #
以下是局部参数示例,不可用来整份替换发行包的 jvm.options。调整时保留前述安全 agent、
-Djava.security.manager=disallow、preview、native access 等必要参数。
生产环境(64 GB 服务器,JDK 25) #
# 堆内存:物理内存的 50%,不超过 31 GB
-Xms31g
-Xmx31g
# G1GC(JDK 11+)
11-:-XX:+UseG1GC
11-:-XX:G1ReservePercent=25
11-:-XX:InitiatingHeapOccupancyPercent=30
# OOM 保护
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=data
-XX:ErrorFile=logs/hs_err_pid%p.log
# GC 日志
9-:-Xlog:gc*,gc+age=trace,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m
# 其他
-Djava.io.tmpdir=${ES_TMPDIR}
开发环境(8 GB 笔记本) #
-Xms1g
-Xmx1g
历史 CMS 配置(JDK 8-10,64 GB 服务器,不适用于 Easysearch 2.5.0) #
-Xms31g
-Xmx31g
# CMS GC(JDK 8-10)
8-10:-XX:+UseConcMarkSweepGC
8-10:-XX:CMSInitiatingOccupancyFraction=75
8-10:-XX:+UseCMSInitiatingOccupancyOnly
# OOM 保护
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=data
-XX:ErrorFile=logs/hs_err_pid%p.log
常见问题 #
启动失败:堆内存分配失败 #
Initial heap size set to an invalid value
通常是因为 -Xms 或 -Xmx 超过了物理内存或操作系统限制。
频繁 Full GC #
- 检查堆大小是否足够。
- 使用
GET _nodes/stats/jvm查看堆使用率。 - 分析 GC 日志(
logs/gc.log)定位原因。
压缩指针未启用 #
堆大小超过约 32 GB 时压缩指针失效。建议设为 31g 或以下。