JVM 偏向锁 4 秒延迟:从源码动机到 JEP-374 废弃全链路
面试高频考点偏向锁为什么要延迟启动启动期到底哪些对象在抢锁后来为什么整个偏向锁都被删了本文所有结论均附 OpenJDK 源码 / JEP 原文出处不杜撰。一、一句话结论BiasedLockingStartupDelay4000默认 4 秒不是专门针对类加载器对象的特殊逻辑而是一个全局时间开关JVM 启动后的前 4 秒内所有新分配对象的 Mark Word 直接是无锁状态不允许匿名偏向4 秒到点后才对当前已加载的所有类和未来新分配的对象开放偏向锁能力。它的唯一目的规避 JVM 启动阶段大量偏向锁撤销触发的安全点SafepointSTW避免拖慢启动速度。二、HotSpot 源码原始注释最权威证据文件hotspot/src/share/vm/runtime/biasedLocking.cppBiasedLocking::init()方法voidBiasedLocking::init(){// If biased locking is enabled, schedule a task to fire a few// seconds into the run which turns on biased locking for all// currently loaded classes as well as future ones. This is a// workaround for startup time regressions due to a large number of// safepoints being taken during VM startup for bias revocation.// Ideally we would have a lower cost for individual bias revocation// and not need a mechanism like this.if(UseBiasedLocking){if(BiasedLockingStartupDelay0){EnableBiasedLockingTask*tasknewEnableBiasedLockingTask(BiasedLockingStartupDelay);task-enroll();}else{VM_EnableBiasedLockingop(false);VMThread::execute(op);}}}逐行翻译这段注释的关键信息原文含义workaround for startup time regressions这是一个临时补丁用来解决启动时间回退问题a large number of safepoints being taken during VM startup for bias revocation根因是启动阶段大量偏向撤销触发安全点 STWIdeally we would have a lower cost for individual bias revocation and not need a mechanism like this理想情况下应该降低单次偏向撤销的开销就不需要这套机制了源码自己都承认这是 workaround不是什么优雅设计。这是面试时可以直接引用的金句。4 秒到点时具体做了什么voidVM_EnableBiasedLocking::doit(){// 1. 遍历系统字典中所有已加载的类把它们的 prototype_header 改为偏向模式SystemDictionary::classes_do(enable_biased_locking);// 2. 标记全局开关未来新分配的对象也走偏向模式_biased_locking_enabledtrue;}两个动作已加载类修改类的prototype_header类的原型对象头之后该类 new 出来的新对象会继承匿名偏向的 Mark Word。未来对象全局开关打开新分配对象默认带匿名偏向标记。注意4 秒前已经分配好的对象Mark Word 不会被回溯修改它们终身是无锁状态不会进入偏向。只有 4 秒之后 new 出来的对象才有资格走偏向锁。三、启动期到底哪些对象在被多线程抢锁3.1 核心判断标准一个对象会在启动期引发锁竞争必须同时满足对象在 JVM 启动极早期被创建落在 0~4 秒窗口内是全局单例所有线程共享同一个对象不是每个线程各 new 一个会被多条不同线程交替访问不是固定一个线程独占3.2 典型对象清单① 各类基础类的Xxx.class对象最典型以java.lang.Integer为例谁在抢主线程、JIT 编译线程、Finalizer 线程、ReferenceHandler 线程几乎同时第一次访问 Integer抢的是什么JVM 规范规定每个类 C 有一个唯一的初始化锁LCHotSpot 的实现就是用Class对象本身当锁为什么必须加锁clinit()静态初始化方法全局只能执行一次多线程同时触发类初始化时必须用锁互斥JLS 12.4.2 原文类初始化详细过程第一步“Synchronize on the initialization lock, LC, for C. This involves waiting until the current thread can acquire LC.”伪代码等价synchronized(Integer.class){// 多个线程抢同一个 Class 对象锁if(Integer已初始化完成)return;Integer.clinit();// 只跑一次初始化 IntegerCache 缓存池标记初始化完成;}关键细节每个类的clinit竞争只发生一次类初始化完成后就不再抢了但启动阶段有几十上百个 JDK 基础类Integer、Long、Boolean、Double、String、Math、ArrayList、HashMap……扎堆并发加载每个类各自发生一次瞬时竞争积少成多。同样的逻辑适用于Long.class、Boolean.class、String.class、Math.class、ArrayList.class、HashMap.class等所有启动期被多线程首次访问的类。② ClassLoadingLock 对象JDK 7ClassLoader.loadClass()不再对this加锁而是调用getClassLoadingLock(className)内部维护一张哈希表key 是类全限定名value 是new Object()锁对象。谁在抢多个线程同时加载同一个类名时拿到同一个锁对象特征对象在类加载过程中创建落在启动窗口内③ JVM 内部全局锁对象C 层映射到 Java 监视器StringTable / SymbolTable 内部锁启动期大量字符串常量 intern、符号插入多线程并发操作哈希表引用队列锁java.lang.ref包静态初始化创建的锁对象协调应用线程、Finalizer 线程、ReferenceHandler 线程SystemDictionary 内部锁类名到 Class 对象的注册表多线程并发查找插入④ 应用代码早期创建的 static 全局锁对象容易被忽略publicclassApp{// 诞生于 0~4 秒窗口哪怕是业务代码 new 的同样禁止匿名偏向publicstaticfinalObjectGLOBAL_LOCKnewObject();}机制只看对象分配时间不看对象属于 JDK 内部还是业务代码。这一点是面试常考的认知误区。3.3 这些对象的共同特征总结┌─────────────────────────────────────────────────┐ │ 启动期高竞争锁对象的共同特征 │ ├─────────────────────────────────────────────────┤ │ 1. 创建时间极早 → 落在 0~4s 偏向锁关闭窗口内 │ │ 2. 全局单例 → 所有线程共享同一个对象 │ │ 3. 多线程交替 → 不是固定一个线程长期持有 │ │ 4. 线程来源杂 → 主线程 JIT 守护线程都来碰 │ └─────────────────────────────────────────────────┘四、如果没有 4 秒延迟会发生什么完整因果链假设设置-XX:BiasedLockingStartupDelay0拿Integer.class走一遍JVM安全点Integer.class对象线程B(JIT线程)线程A(主线程)JVM安全点Integer.class对象线程B(JIT线程)线程A(主线程)对象分配Mark Word 匿名偏向(101)Mark Word 已偏向A(101线程A指针)发现锁已偏向AA已退出同步块Mark Word 退回无锁(001)抢锁CAS成功对象偏向线程A执行clinit释放锁来抢同一把锁触发全局安全点STW暂停所有Java线程遍历线程栈撤销偏向标记升级轻量级锁CAS抢轻量级锁成功每一次别的线程来抢一个已被偏向的对象都要走一次全局安全点 STW。启动期几十个类各来一次STW 次数爆炸启动时间显著拉长。这就是源码注释说的 “a large number of safepoints being taken during VM startup for bias revocation”。五、4 秒延迟的本质不是识别对象是按时间一刀切0sJVM启动新对象 Mark Word 无锁(001)禁止匿名偏向4sEnableBiasedLockingTask触发已加载类的prototype_header改为偏向模式全局开关_biased_locking_enabled true4s新对象 Mark Word 匿名偏向(101)允许走偏向锁逻辑对象分配时间 vs 偏向锁能力两个常见误区误区真相4 秒后老对象也会自动变成可偏向❌ 不会。只有 4 秒后 new 出来的对象才有匿名偏向标记老对象终身无锁4 秒延迟是专门识别、过滤 JVM 内部对象❌ 没有特殊识别逻辑纯粹按对象分配时间一刀切。业务代码在启动前 4 秒 new 的对象同样不能偏向六、后来为什么把整个偏向锁都删了JEP-3746.1 版本时间线版本事件出处JDK 6引入偏向锁默认开启—JDK 152020.09默认关闭偏向锁废弃所有相关参数JEP-374JDK 18彻底删除偏向锁代码参数不再识别obsoleteJDK-8256425原本计划 JDK 16 删除后延期到 JDK 18JDK-8256253。被废弃的参数清单JEP-374 原文列出ProductBiasedLockingStartupDelay、BiasedLockingBulkRebiasThreshold、BiasedLockingBulkRevokeThreshold、BiasedLockingDecayTime、UseOptoBiasInliningDiagnosticPrintBiasedLockingStatistics、PrintPreciseBiasedLockingStatistics6.2 废弃的四大原因JEP-374 Motivation 原文归纳① 硬件变化CAS 原子指令成本大幅下降JEP 原文“The cost of executing atomic instructions has decreased on modern processors since the introduction of biased locking into HotSpot.”偏向锁诞生的初衷是省去 CAS 原子操作。当年 CAS 很贵今天 CAS 已经很便宜偏向锁省下来的那点开销微不足道。② 受益场景萎缩只有老应用还在吃红利JEP 原文“Many applications that benefited from biased locking are older, legacy applications that use the early Java collection APIs, which synchronize on every access (e.g., Hashtable and Vector).”老应用Hashtable、Vector——每次访问都 synchronized单线程场景下偏向锁收益大现代应用HashMap、ArrayListJava 1.2 引入单线程无锁或ConcurrentHashMapJava 5 引入高并发本身就减少了不必要的 synchronized③ 线程池架构的应用关闭偏向锁反而更快JEP 原文“applications built around a thread-pool queue and worker threads generally perform better with biased locking disabled. (SPECjbb2015 was designed that way)”现代微服务基本都是线程池 Worker 线程架构。同一个锁对象在不同 Worker 线程之间频繁换手一旦竞争就触发偏向撤销 STWP99 延迟恶化。SPECjbb2015 基准测试就是关闭偏向锁后性能更好。④ 维护成本太高阻碍 JVM 演进JEP 原文“Biased locking introduced a lot of complex code into the synchronization subsystem and is invasive to other HotSpot components as well. This complexity is a barrier to understanding various parts of the code and an impediment to making significant design changes.”偏向锁的状态机极其复杂匿名偏向、已偏向、批量重偏向bulk rebias、批量撤销bulk revoke、epoch 机制、线程死亡处理……代码侵入线程、GC、解释器、JIT 各个模块。Project Loom虚拟线程要改造同步子系统时偏向锁是巨大障碍。6.3 关键澄清不是启动期锁竞争被解决了误区JDK 优化了启动期不再多线程初始化基础类所以不需要 4 秒延迟了。真相类加载并发逻辑、clinit锁机制几乎没有改动。启动期Integer.class等对象依旧会被多线程争抢只是现在直接走轻量级锁 CAS不再有偏向→撤销→STW这条路径自然也就不需要 4 秒这个补丁了。七、全链路因果图面试默写版JDK6 引入偏向锁目的: 单线程反复拿锁时省去CAS问题: 别的线程来抢已偏向对象时必须触发全局安全点STW做撤销JVM启动期: 几十上百个基础类被主线程JIT守护线程并发初始化每个类的Xxx.class都是全局单例锁对象多线程争抢 → 大量偏向撤销 → 大量STW启动时间严重回退打补丁: BiasedLockingStartupDelay4000前4秒新对象禁止匿名偏向4秒后: 已加载类prototype_header改偏向模式新对象允许匿名偏向时代变化硬件: CAS变便宜了应用: 线程池架构, 锁频繁换手偏向撤销STW反而恶化P99代码: 状态机太复杂, 阻碍虚拟线程等新特性JEP-374: JDK15默认关闭JDK18: 彻底删除代码, 参数obsolete4秒延迟随偏向锁一起消失启动期竞争直接走轻量级锁CAS八、面试高频 QAQ1偏向锁为什么要延迟 4 秒启动答不是为了等什么而是为了避开 JVM 启动阶段的高竞争期。启动期大量基础类的Class对象、ClassLoadingLock、JVM 内部全局锁对象会被主线程、JIT 线程、守护线程并发争抢。如果一启动就开启偏向锁这些对象会频繁经历偏向→被别的线程抢→安全点 STW 撤销的循环大量 STW 拖慢启动。所以前 4 秒新对象直接无锁4 秒后启动期高竞争基本结束再开放偏向锁。Q24 秒延迟是专门针对类加载器对象吗答不是。它是按对象分配时间的全局一刀切开关不识别对象类型。类加载器相关锁对象确实是启动期高竞争对象的典型代表但业务代码在前 4 秒 new 的对象同样被禁止偏向。Q34 秒后之前创建的对象会变成可偏向吗答不会。4 秒到点时只做两件事修改已加载类的prototype_header、打开全局开关。已经分配好的对象 Mark Word 不会被回溯修改它们终身是无锁状态。只有 4 秒之后 new 出来的对象才有匿名偏向标记。Q4偏向锁撤销为什么需要安全点 STW答撤销偏向时需要遍历所有线程的栈找到并修改那些正在使用该偏向锁的栈帧中的锁记录确保递归锁等场景的一致性。遍历线程栈必须在所有线程都暂停的安全点才能安全进行所以是全局 STW。这也是偏向锁撤销代价高的根本原因。Q5JDK 15 之后偏向锁怎么了答JDK 15 通过 JEP-374 默认关闭偏向锁并废弃相关参数JDK 18 彻底删除偏向锁代码UseBiasedLocking、BiasedLockingStartupDelay等参数不再被识别。原因是现代 CPU 的 CAS 开销降低、线程池架构下偏向锁反而制造延迟抖动、代码复杂度阻碍虚拟线程等新特性演进。Q6启动期Integer.class的锁竞争会持续很久吗答不会。每个类的clinit只执行一次初始化完成后其他线程直接返回不再争抢。但启动期有几十上百个基础类扎堆并发初始化每个类瞬时竞争一次累积起来的偏向撤销 STW 次数就很可观了。九、参考来源OpenJDK 源码hotspot/src/share/vm/runtime/biasedLocking.cpp—BiasedLocking::init()原始注释JEP 374: Deprecate and Disable Biased Locking — http://openjdk.org/jeps/374JDK-8256425: Obsolete Biased Locking in JDK 18 — https://bugs.openjdk.org/browse/JDK-8256425JLS 12.4.2 Detailed Initialization Procedure — 类初始化锁LC规范OpenJDK Wiki: Biased-locking Synchronization —BiasedLockingStartupDelay参数说明

相关新闻

选题卡壳、文献一查就假?2026写论文按四类AI分工,开题和引用格式用毕业之家兜底

选题卡壳、文献一查就假?2026写论文按四类AI分工,开题和引用格式用毕业之家兜底

又到开学季,后台被问最多的问题永远是:“写论文到底用哪个AI?” 说实话,2026年了,还在指望"一个ChatGPT从头写到尾"的同学,基本已经在AIGC检测和导师的火眼金睛面前栽过跟头了。现在的工具生态早…

2026/9/3 15:23:34 阅读更多 →
春季笔记1

春季笔记1

数据库(DB)一、定义 数据库(DataBase)为了方便数据的存储和管理&#xff0…

2026/9/4 15:37:08 阅读更多 →
论文人别再瞎折腾了:从选题到降重,2026年最省心的AI工具组合方案(附免费查重入口)

论文人别再瞎折腾了:从选题到降重,2026年最省心的AI工具组合方案(附免费查重入口)

又到毕业季,后台被问最多的问题就是:“查重到底用哪个?”“AI写的会不会被检测出来?”“有没有不花钱又靠谱的工具?” 作为一个刚把论文送审、重率从28%干到7%的过来人,我把这两年用过的查重平台、大模型、…

2026/9/3 15:23:34 阅读更多 →

最新新闻

204、【Agent】【OpenCode】TUI 内部:SDK 客户端与事件流

204、【Agent】【OpenCode】TUI 内部:SDK 客户端与事件流

【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除 标题 204、【Agent】【OpenCode】TUI 内部&am…

2026/9/4 18:00:43 阅读更多 →
NetExec 命令总结

NetExec 命令总结

天有阴阳风雨晦明之气,人有喜怒哀乐好恶之情。 导航 工具介绍命令语法支持协议杂项 工具介绍NetExec(又称 nxc)是一款网络服务漏洞利用工具,它是 CrackMapExec 的延续,且支持的 协议、模块、功能 相较前者更为丰富。 …

2026/9/4 18:00:43 阅读更多 →
机器学习learing-One

机器学习learing-One

机器学习 一、机器学习介绍 1.人工智能三大概念 人工智能之父:约翰麦卡锡 机器学习之父:亚瑟塞缪尔 人工智能: 用计算机模拟人脑,让计算机像人类一样理性地思考和行动 机器学习(ML): Machine Le…

2026/9/4 18:00:43 阅读更多 →
秋叶ComfyUI整合包V17部署指南:从零搭建Stable Diffusion节点工作流

秋叶ComfyUI整合包V17部署指南:从零搭建Stable Diffusion节点工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/4 18:00:43 阅读更多 →
不止于看:硬件电路设计实战专栏的权益与成长计划

不止于看:硬件电路设计实战专栏的权益与成长计划

感谢您对本专栏的兴趣!这个专栏以大概59.9元的价格(由于支付方式问题各平台会存在微小差异)提供超过100个电路设计案例,旨在帮助刚毕业不久或已工作硬件工程师快速成长。通过系统剖析核心电路原理图、设计规范和实战案例,本专栏不仅讲解知识案…

2026/9/4 18:00:43 阅读更多 →
multi-agent-brainstorming - SKILL

multi-agent-brainstorming - SKILL

name: multi-agent-brainstorming description: “Simulate a structured peer-review process using multiple specialized agents to validate designs, surface hidden assumptions, and identify failure modes before implementation.” risk: none source: community dat…

2026/9/4 17:59:42 阅读更多 →

日新闻

ESP32S2嵌入式收音机全栈开发实战指南

ESP32S2嵌入式收音机全栈开发实战指南

简介:本资源是一个基于ESP32-S2芯片的嵌入式综合实践项目,面向本科毕业设计、课程设计及实训开发人员,聚焦网络收音机与FM收音机双模功能实现,融合ESP-IDF框架、ESP-ADF音频开发库与LVGL图形界面库,具备完整软硬件协同…

2026/9/4 0:00:28 阅读更多 →
WorkBuddy+Python实战:从零搭建商品库存管理系统

WorkBuddy+Python实战:从零搭建商品库存管理系统

最近想自己动手做一个“商品库存管理系统”的人变多了。很多开网店、做小团队ERP选型、或者刚学Python的读者,不是不想用系统,而是被传统开发路径劝退了:要装数据库,要写后端接口,要学前端页面,还要考虑多人…

2026/9/4 0:00:28 阅读更多 →
旅游情感分析:基于Python的垂直场景深度解析

旅游情感分析:基于Python的垂直场景深度解析

简介:本资源是一份面向计算机专业本科生的毕业设计实践项目,聚焦旅游行业真实场景,解决旅游平台对用户评论情感倾向自动识别与管理的需求。系统基于Python 3.9.11与Anaconda环境构建,集成携程、马蜂窝双平台爬虫模块,并…

2026/9/4 0:00:28 阅读更多 →

周新闻

备战数据库管理工程师校招:索引、事务、备份恢复核心考点解析

备战数据库管理工程师校招:索引、事务、备份恢复核心考点解析

每年校招季我都会接触不少准备数据库方向笔试的同学,看到最多的状态就是:简历上写着“熟悉 MySQL”“了解索引优化”,一碰到数据库管理工程师的笔试卷,却在索引、事务、锁、备份恢复这些题目上翻车。网易这套 2018 校园招聘数据库…

2026/9/4 10:54:27 阅读更多 →
数字电路时序基石:深入理解建立时间与保持时间

数字电路时序基石:深入理解建立时间与保持时间

1. 这不是“背公式”的事:时间参数到底在约束什么你翻过数字电路教材,一定见过这两个词:建立时间(Setup Time)和保持时间(Hold Time)。它们常被并列写在触发器(Flip-Flop&#xff09…

2026/9/4 14:20:02 阅读更多 →
蓝桥杯国赛超声波测距机:从单片机原理到嵌入式系统实战

蓝桥杯国赛超声波测距机:从单片机原理到嵌入式系统实战

1. 项目缘起:从赛题到超声波测距机的诞生第八届蓝桥杯单片机设计与开发国赛的题目,我至今记忆犹新。它没有直接给出一个花哨的名字,而是用“超声波测距机”这个朴实无华的功能描述,精准地勾勒出了考核的核心。对于当时备赛的我而言…

2026/9/3 4:22:59 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/3 4:17:49 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/3 4:18:56 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/4 9:37:01 阅读更多 →