
java 13 起默认禁用偏向锁(biased locking),而 jess 大量依赖 `synchronized` 方法和对象(如 `collections.synchronizedmap`),导致原有轻量级同步机制失效,引发显著性能下降。
Jess 是一款历史悠久的 Java 规则引擎,其核心代码基于 Java 1.5 编写,广泛使用 synchronized 关键字实现线程安全(如 findVariable() 和 getVariables() 方法所示)。这类设计在 Java 6–11 时期运行高效,主要原因在于 偏向锁(Biased Locking)默认启用——当一个对象被同一线程反复加锁时,JVM 会将其“偏向”该线程,避免进入重量级锁(monitor)路径,大幅降低同步开销。
然而,自 Java 13 起(JEP 374),偏向锁被默认禁用(-XX:+UseBiasedLocking 已设为 false),并在 Java 15 中正式移除。这意味着:
✅ 所有 synchronized 块/方法(包括 Collections.synchronizedMap 的内部锁)均跳过偏向锁阶段,直接进入轻量级锁甚至重量级锁竞争路径;
✅ Jess 中高频调用的 findVariable()(逐层向上查找变量)、getVariables()(懒初始化同步 Map)等方法,在规则匹配密集场景下会触发大量锁膨胀与上下文切换;
✅ 多个此类方法叠加,正是你观察到的「30–40% 整体性能下降」的根本原因——并非单点瓶颈,而是同步原语语义变更引发的系统性退化。
✅ 快速验证与临时修复
在启动 Jess 应用时显式启用偏向锁(仅限 Java 13–14,Java 15+ 不支持):
java -XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0 -jar your-app.jar
⚠️ 注意:BiasedLockingStartupDelay=0 可避免延迟启用导致的初期抖动;Java 15+ 需降级至 Java 14 或采用其他方案。
✅ 长期优化建议
-
替换同步容器:将 Collections.synchronizedMap(new HashMap()) 替换为 ConcurrentHashMap(无需外部同步),并移除 synchronized 修饰符:
private final ConcurrentHashMap
m_variables = new ConcurrentHashMap<>(); private Map getVariables() { return m_variables; // 无须同步,ConcurrentHashMap 线程安全 } -
消除冗余同步:findVariable() 中的 synchronized 方法锁粒度过大(锁住整个 Context 实例),可改为细粒度锁或无锁设计(如 ThreadLocal 缓存常用变量映射)。
立即学习“Java免费学习笔记(深入)”;
升级或迁移:考虑迁移到现代规则引擎(如 Drools、Easy Rules),或联系 Jess 维护方获取兼容 Java 17+ 的补丁版本。
总结
这不是 JVM 的“bug”,而是 JVM 同步机制演进与老旧代码耦合的典型冲突。根本解法是重构同步逻辑,而非依赖已淘汰的偏向锁。在无法立即重构时,Java 13–14 下启用 -XX:+UseBiasedLocking 是最直接有效的过渡方案。











