
java 11 升级至 java 17 后 jess 运行变慢 30–40%,主因是 jdk 15 起默认禁用偏向锁(biased locking),而 jess 大量使用 synchronized 方法(如 findvariable、getvariables)严重依赖该机制,导致锁膨胀为重量级锁,引发显著性能下降。
Jess 是一款历史悠久的 Java 规则引擎,其核心代码基于 Java 1.5 编写,广泛采用 synchronized 关键字实现线程安全——例如您提供的 findVariable() 和 getVariables() 方法,均被声明为 synchronized,且在执行链中高频调用(如上下文逐层回溯、变量哈希表懒加载等)。这类细粒度同步在早期 JVM(Java 8/11)中通常由偏向锁(Biased Locking) 高效支撑:当一个线程首次获取锁时,JVM 会将对象头标记为“偏向该线程”,后续同一线程重入无需原子操作,开销近乎为零。
然而,从 JDK 15 开始(JEP 374),偏向锁被默认禁用(-XX:+UseBiasedLocking 已失效),并在 JDK 16 中彻底移除。尽管 Java 13–14 已开始逐步弱化其默认启用状态(部分发行版默认关闭),但 Oracle、Eclipse Temurin、Azul Zulu 等主流 JDK 在 13+ 版本中普遍已不再启用偏向锁。这意味着:
- 所有原本可偏向的对象锁,现直接升级为轻量级锁甚至重量级锁(OS Mutex);
- 每次 synchronized 进入/退出均需 CAS 操作或内核态切换;
- 对于 Jess 这类存在深度嵌套调用、高频率短临界区(如每次规则匹配都触发多次 findVariable)的场景,锁争用成本呈数量级上升。
? 验证方法:
在 Java 17+ 启动参数中显式启用(若支持)或禁用偏向锁,对比性能:
# 尝试恢复(仅适用于 JDK 15–16,JDK 17+ 不再支持) -XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0 # 或强制禁用以确认影响(Java 11 下也适用作基线对照) -XX:-UseBiasedLocking
若 Java 11 下添加 -XX:-UseBiasedLocking 后性能骤降,而 Java 17 下添加 -XX:+UseBiasedLocking 无效(报 Unrecognized VM option),即可确认问题根源。
✅ 推荐解决方案:
立即学习“Java免费学习笔记(深入)”;
- 短期兼容:降级至 JDK 11 LTS(长期支持、偏向锁默认启用且稳定);
-
中期优化:对 Jess 关键路径进行轻量改造,消除不必要同步:
- getVariables() 可改用 ConcurrentHashMap + computeIfAbsent 替代 Collections.synchronizedMap(new HashMap());
- findVariable() 中的 synchronized 可移至更粗粒度作用域,或结合 ThreadLocal
缓存常用上下文;
- 长期替代:评估现代规则引擎迁移(如 Drools、Easy Rules),其原生支持 Java 17+ 并采用无锁/分段并发设计。
⚠️ 注意:勿盲目添加 -XX:BiasedLockingStartupDelay=0 或其他过时参数——JDK 17+ 已完全移除相关逻辑,强行配置将导致启动失败。性能调优应以实际 profiler(如 JFR、Async Profiler)数据为准,重点关注 ObjectSynchronizer::fast_enter、Mutex::lock 等锁相关热点。
总结而言,这不是 JVM 的“bug”,而是旧代码与新 JVM 优化策略演进之间的典型适配断层。理解锁机制变迁,比单纯回滚 JDK 更具可持续性。











