当前位置: 首页 > article >正文

JVM对象头中的锁信息机制详解

JVM对象头中的锁信息机制详解

Java中的对象锁机制是高性能并发的基石,而这一切的底层实现都离不开对象头中的 Mark Word 字段。本文将系统梳理JVM对象头中锁信息的存储与演化机制,解析锁升级与批量重偏向优化原理,并通过JOL工具实战验证对象头的实际变化。


一、对象头与Mark Word结构

每个Java对象在内存中的布局如下(64位JVM,开启指针压缩):

字段大小说明
Mark Word64 bits存储锁信息、哈希码、GC年龄等
Klass Pointer32 bits指向类元数据
Array Length32 bits仅数组对象,记录长度

Mark Word的动态结构

Mark Word 的内容根据锁状态动态变化,主要分为以下几种:

状态标志位存储内容(64位)适用场景
无锁01哈希码31bit、GC年龄4bit、未用位、偏向位无竞争
偏向锁01线程ID54bit、epoch2bit、GC年龄4bit、偏向位单线程独占
轻量级锁00指向栈中锁记录的指针62bit低并发、短同步块
重量级锁10指向Monitor(OS互斥量)指针62bit高并发、长耗时临界区
GC标记11空值,用于GC标记GC期间

二、锁状态的升级与降级机制

JVM采用不可逆锁升级策略,根据竞争强度动态提升锁级别,避免频繁的锁降级带来的性能问题。

首次线程访问
其他线程竞争
自旋失败
批量重偏向
批量撤销
锁释放无竞争
锁释放
无锁
偏向锁
轻量级锁
重量级锁

各锁状态简析

  • 偏向锁:第一次线程访问时,Mark Word“贴标签”记录线程ID,后续该线程进入同步块无需CAS,极致优化无竞争场景。
  • 轻量级锁:当有第二个线程竞争时,通过CAS将Mark Word复制到线程栈中的锁记录(Lock Record),自旋尝试获取锁。
  • 重量级锁:自旋失败或竞争激烈时,升级为重量级锁,对象头指向Monitor,线程进入阻塞队列,由操作系统调度。

锁升级示例

public class Counter {private int count = 0;private final Object lock = new Object();public void increment() {synchronized(lock) {count++;}}public static void main(String[] args) {Counter counter = new Counter();// 1. 单线程独占(偏向锁)IntStream.range(0, 100).forEach(i -> counter.increment());// 2. 两线程交替访问(轻量级锁)new Thread(() -> IntStream.range(0, 100).forEach(i -> counter.increment())).start();new Thread(() -> IntStream.range(0, 100).forEach(i -> counter.increment())).start();// 3. 多线程竞争(重量级锁)ExecutorService pool = Executors.newFixedThreadPool(10);IntStream.range(0, 1000).forEach(i -> pool.submit(counter::increment));}
}

三、偏向锁批量重偏向机制(epoch优化)

1. 触发条件

  • 某个类的对象被不同线程撤销偏向锁超过阈值(默认20次,可用 -XX:BiasedLockingBulkRebiasThreshold 调整)。
  • 达到更高阈值(默认40次,-XX:BiasedLockingBulkRevokeThreshold)后,彻底禁用该类偏向锁

2. epoch机制实现

  • 每个类维护一个全局epoch值,对象头Mark Word中记录当前epoch副本。
  • 发生批量重偏向时,类的epoch+1,无需遍历对象头一一CAS,只需访问时对比epoch。
  • 访问对象时,若对象头epoch与类epoch不一致,则允许重新偏向新线程。
示例代码
public class BulkRebiasDemo {public static void main(String[] args) {List<Object> list = new ArrayList<>();// 阶段1:A线程创建并偏向100个对象for (int i = 0; i < 100; i++) {Object obj = new Object();synchronized(obj) {} // 偏向线程Alist.add(obj);}// 阶段2:B线程访问这些对象new Thread(() -> {for (Object obj : list) {synchronized(obj) {// 前20次撤销,后续批量重偏向}}}).start();}
}

3. 优势

  • 批量操作:O(N)次CAS变为O(1)全局epoch更新,大幅降低锁撤销开销。
  • 性能提升:高并发下减少CPU颠簸,提升吞吐量。

四、JVM对象头结构与验证

1. JOL工具实战

JOL (Java Object Layout) 可直接查看对象头布局:

Maven依赖:

<dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.17</version>
</dependency>

验证代码:

public static void main(String[] args) {Object obj = new Object();System.out.println(ClassLayout.parseInstance(obj).toPrintable());int[] arr = new int[3];System.out.println(ClassLayout.parseInstance(arr).toPrintable());
}

输出示例(64位JVM,压缩指针):

java.lang.Object object internals:OFFSET  SIZE   TYPE DESCRIPTION0     4        (object header)    # Mark Word4     4        (object header)    # 类型指针8     4        (object header)    # 数组长度(数组对象)12     4        (loss due to...)[I object internals:OFFSET  SIZE   TYPE DESCRIPTION0     4        (object header)    # Mark Word4     4        (object header)    # 类型指针8     4        (object header)    # 数组长度=312    12    int [I.<elements>      # 数组元素24     4        (loss due to...)

2. 锁状态变化观测

Object lock = new Object();
System.out.println("初始状态:" + ClassLayout.parseInstance(lock).toPrintable());synchronized(lock) {System.out.println("加锁状态:" + ClassLayout.parseInstance(lock).toPrintable());
}
  • 关注Mark Word最后2~3位:01(无锁/偏向锁)、00(轻量级锁)、10(重量级锁)

五、性能影响与优化建议

锁类型适用场景性能特点优化建议
偏向锁单线程独占零额外开销-XX:BiasedLockingStartupDelay=0
轻量级锁低并发短同步块自旋消耗CPU控制自旋次数(-XX:PreBlockSpin)
重量级锁高并发/长临界区上下文切换开销大减少同步块粒度
批量重偏向高并发多线程访问O(1)批量优化,减少CAS合理设置阈值,避免频繁撤销

六、总结

  • 对象头中的Mark Word是Java对象锁实现的核心,能够动态存储锁状态、线程ID、指针等信息。
  • 锁升级不可逆,保证了线程安全和性能的平衡。
  • 批量重偏向机制通过epoch优化,将大量CAS操作降为常数级epoch对比,极大提升高并发下的锁撤销效率。
  • 借助JOL工具,开发者可直观观测对象头在不同锁状态下的变化,为并发调优提供有力支撑。

理解JVM对象头中的锁机制,有助于我们写出更高效、更具可预测性的并发代码。欢迎大家用JOL实战,深度探索Java对象的“内在世界”!


参考资料:

  • Java官方JVM文档
  • JOL项目主页
  • 深入理解Java虚拟机

相关文章:

JVM对象头中的锁信息机制详解

JVM对象头中的锁信息机制详解 Java中的对象锁机制是高性能并发的基石&#xff0c;而这一切的底层实现都离不开对象头中的 Mark Word 字段。本文将系统梳理JVM对象头中锁信息的存储与演化机制&#xff0c;解析锁升级与批量重偏向优化原理&#xff0c;并通过JOL工具实战验证对象…...

Java设计模式之适配器模式:从入门到精通

适配器模式(Adapter Pattern)是Java中最常用的结构型设计模式之一,它像一座桥梁连接两个不兼容的接口,使得原本由于接口不兼容而不能一起工作的类可以协同工作。本文将全面深入地解析适配器模式,从基础概念到高级应用,包含丰富的代码示例、详细注释、使用场景分析以及多维对…...

英伟达Blackwell架构重构未来:AI算力革命背后的技术逻辑与产业变革

——从芯片暴力美学到分布式智能体网络&#xff0c;解析英伟达如何定义AI基础设施新范式 开篇&#xff1a;当算力成为“新石油”&#xff0c;英伟达的“炼油厂”如何升级&#xff1f; 2025年3月&#xff0c;英伟达GTC大会上&#xff0c;黄仁勋身披标志性皮衣&#xff0c;宣布了…...

【自定义指令】(el-table表格内容自动轮播)

// el-table 自动轮播 import { nextTick } from vue; export default {bind(el, binding) {const time binding.value?.time || 100;let speed binding.value?.speed || 1;const loop binding.value?.loop || true;const timeLoop binding.value?.timeLoop || true;co…...

深度拆解!MES如何重构生产计划与排产调度全流程?

☂引言 在制造业数字化转型浪潮中&#xff0c;生产计划与排产调度的精准性直接决定企业竞争力。深蓝易网MES系统通过智能化调度与全流程管控&#xff0c;帮助企业破解排产难题&#xff0c;实现资源高效协同与生产透明化管理&#xff0c;为制造企业打造柔性化、敏捷化的生产体系…...

信息系统项目管理师-软考高级(软考高项)​​​​​​​​​​​2025最新(十八)

个人笔记整理---仅供参考 第十八章项目绩效域 18.1干系人绩效域 18.2团队绩效域 18.3开发方法和生命周期绩效域 18.5项目工作绩效域 18.6交付绩效域 18.7度量绩效域 18.8不确定绩效域...

UniDevTools - UniApp(前端app)调试工具使用

使用介绍 | UniDevTools 兼容框架&#xff1a; Vue2jsvuexVue3tsvuex(pinia)√√ 兼容平台&#xff1a; H5APP微信小程序APP-NVUE其他小程序UniAppX√√√√(大部分功能支持)未测试 (待办中) 下载安装 将下载好的源码解压至项目根目录&#xff0c;文件夹命名为 devTools …...

WebRTC工作原理详细介绍、WebRTC信令交互过程和WebRTC流媒体传输协议介绍

简介 WebRTC&#xff08;Web Real-Time Communication&#xff09;是一项允许在网页浏览器之间进行音视频通信的技术&#xff0c;基本不需要安装额外的插件。它的核心特点是支持低延迟的点对点&#xff08;P2P&#xff09;通讯&#xff0c;常用于视频聊天、实时文件共享、多人…...

Docker快速入门与应用

1. 什么是 Docker&#xff1f; Docker 就像一个“魔法箱子”&#xff0c;可以把你开发的应用&#xff08;代码、环境、配置&#xff09;‌打包成一个标准化的容器‌&#xff0c;这个容器可以在任何支持 Docker 的系统上运行&#xff0c;无需担心环境差异导致的问题。 ‌类比‌…...

Spring Boot 启动原理的核心机制

一、核心启动流程概览 Spring Boot 的启动流程可概括为 ​7 个关键阶段​&#xff1a; 1. 加载启动类 (Main Class) 2. 初始化 SpringApplication 实例 3. 加载配置 & 准备环境 (Environment) 4. 创建 ApplicationContext&#xff08;容器&#xff09; 5. 刷新容器&#…...

spring中的@Lazy注解详解

一、核心功能与作用 Lazy 注解是 Spring 框架中用于延迟 Bean 初始化的核心工具&#xff0c;通过将 Bean 的创建推迟到首次使用时&#xff0c;优化资源利用和启动性能。其核心功能包括&#xff1a; 延迟初始化 默认情况下&#xff0c;Spring 在容器启动时立即初始化所有单例 …...

视觉-语言-动作模型:概念、进展、应用与挑战(上)

25年5月来自 Cornell 大学、香港科大和希腊 U Peloponnese 的论文“Vision-Language-Action Models: Concepts, Progress, Applications and Challenges”。 视觉-语言-动作 (VLA) 模型标志着人工智能的变革性进步&#xff0c;旨在将感知、自然语言理解和具体动作统一在一个计…...

语义分割模型部署到嵌入式终端的通用操作流程

以下是语义分割模型部署到嵌入式终端的通用操作流程&#xff0c;结合不同硬件平台&#xff08;如华为Atlas、地平线J5、树莓派等&#xff09;的共性需求整理而成&#xff1a; 一、环境准备与工具链配置 1. 嵌入式开发环境搭建 安装交叉编译工具链&#xff08;如ARM-GCC&…...

R1-Searcher:用强化学习解锁大语言模型检索新能力!

R1-Searcher&#xff1a;用强化学习解锁大语言模型检索新能力&#xff01; 大语言模型&#xff08;LLMs&#xff09;发展迅猛&#xff0c;却常因依赖内部知识而在复杂问题上“栽跟头”。今天解读的论文提出R1-Searcher框架&#xff0c;通过强化学习提升LLMs检索能力。它表现超…...

第一篇 世界观安全

目录 STRIDE模型 五大原则 一黑白名单 二最小权限原则 三纵深防御原则 四数据和代码分离 五不可预测原则 安全的问题本质是信任问题。 并且安全是一个持续的过程。 安全的三要素&#xff1a;机密性&#xff0c;完整性&#xff08;可以采用数字签名&#xff09;&#x…...

RNN(循环神经网络)原理与结构

1 RNN&#xff08;循环神经网络&#xff09;原理与结构 循环神经网络&#xff08;Recurrent Neural Network, RNN&#xff09;是一类专门用于处理序列数据&#xff08;如时间序列、文本、语音等&#xff09;的深度学习模型。与传统的前馈神经网络不同&#xff0c;RNN在每个时间…...

mac M2能安装的虚拟机和linux系统系统

目前网上的资料大多错误&#xff0c;能支持M2的很少。 推荐安装的改造过的centos7也无法进行yum操作&#xff0c;建议安装centos8 VMware Fusion下载地址&#xff1a; https://pan.baidu.com/s/14v3Dy83nuLr2xOy_qf0Jvw 提取码: jri4 centos8下载地址&#xff1a; https://…...

无偿帮写毕业论文

以下教程教你如何利用相关网站和AI免费帮你写一个毕业论文。毕竟毕业论文只要过就行&#xff0c;脱产学习这么多年&#xff0c;终于熬出头了&#xff0c;完成毕设后有空就去多看看亲人好友&#xff0c;祝好&#xff01; 一、找一个论文模板(最好是overleaf) 废话不多说&#…...

智能网联汽车“内外协同、虚实共生”的通信生态

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 钝感力的“钝”&#xff0c;不是木讷、迟钝&#xff0c;而是直面困境的韧劲和耐力&#xff0c;是面对外界…...

Linux操作系统从入门到实战(六)Linux开发工具(上)详细介绍什么是软件包管理器,Linux下如何进行软件和软件包的安装、升级与卸载

Linux操作系统从入门到实战&#xff08;六&#xff09;Linux开发工具&#xff08;上&#xff09;详细介绍什么是软件包管理器&#xff0c;Linux下如何进行软件和软件包的安装、升级与卸载 前言一、 软件包管理器1.1 传统安装方式的麻烦&#xff1a;从源代码说起1.2 软件包&…...

物流无人机自动化装卸技术解析!

一、自动化装卸技术模块的技术难点 1. 货物多样性适配 物流场景中货物包装类型、尺寸、材质差异大&#xff0c;如农产品、医疗物资、工业设备等&#xff0c;要求装卸模块具备高度柔性化设计。例如&#xff0c;单元货物需视觉识别系统进行单个抓取&#xff0c;而整托货物需大…...

基于构件的开发方法与传统开发方法的区别

在软件开发领域,基于构件的开发方法和传统开发方法有着截然不同的特点与应用效果,这些差异显著影响着项目的实施过程与最终成果。下面,我们将从多个关键维度展开对比分析。​ 一、开发模式:线性搭建与模块组装​ 传统开发方法遵循线性的、自顶向下的流程,就像搭建一座高楼…...

详解 IRC协议 及客户端工具 WeeChat 的使用

本文将详细介绍 Internet Relay Chat&#xff08;IRC&#xff09;协议及其历史、基本概念、核心功能&#xff0c;以及流行的 IRC 客户端 WeeChat 的安装、配置和使用方法。内容力求准确、详尽&#xff0c;涵盖 IRC 的技术背景、使用场景&#xff0c;以及 WeeChat 的高级功能和实…...

IOT藍牙探測 C2 架構:社會工程/節點分離防追尋

BMC 地址:https://github.com/MartinxMax/bmc/releases/tag/V1.5 藍牙 MAC 偵測節點的物聯網分散式 C2 架構&#xff0c;可與 S-Cluster 交互。 場景 A&#xff1a;潛伏偵測 駭客組織會將 BMC 裝置秘密部署在目標建築物周圍&#xff08;例如牆外、通風口或垃圾間等隱蔽地點&…...

Koa知识框架

一、核心概念 1. 基本特点 由 Express 原班人马开发的下一代 Node.js Web 框架 基于中间件的洋葱圈模型 轻量级核心&#xff08;仅约 600 行代码&#xff09; 完全使用 async/await 异步流程控制 没有内置任何中间件&#xff0c;高度可定制 2. 核心对象 Application (Ko…...

FreeRTOS学习记录(变量命名规则全解、文件介绍)

目录 FreeRTOS 变量命名规则详解​ ​一、变量命名前缀规则​ &#xff08;一&#xff09;数据类型相关前缀​ &#xff08;二&#xff09;功能模块相关前缀​ &#xff08;三&#xff09;宏定义 二、变量命名与文件的关系​ &#xff08;一&#xff09;核心源文件中的变…...

Qt 中 QWidget涉及的常用核心属性介绍

欢迎来到干货小仓库 一匹真正的好马&#xff0c;即使在鞭子的影子下&#xff0c;也能飞奔 1.enabled API说明isEnabled()获取到控件的可用状态setEnabled()设置控件是否可使用.true&#xff1a;可用&#xff0c;false&#xff1a;禁用 禁用&#xff1a;指该控件不能接收任何用…...

Open CASCADE学习|由大量Edge构建闭合Wire:有序与无序处理的完整解析

在CAD建模中,构建闭合的Wire(线框)是拓扑结构生成的基础操作。OpenCascade(OCCT)作为强大的几何建模库,支持从离散的Edge(边)构建Wire,但在实际应用中,边的有序性直接影响构建的成功率。本文将详细探讨有序与无序两种场景下的实现方法,并提供完整代码示例。 一、有序…...

linux 开发小技巧之git增加指令别名

众所周知&#xff0c;git的指令执行时都得敲好几个字符才能补充上来&#xff0c;比如常用的git status&#xff0c;是不是要将全部的字符一个个地在键盘敲上来&#xff0c;有没有更懒惰点办法&#xff0c;可以将经常用到的git命令通过其他的别名的方式填充&#xff0c;比如刚刚…...

一文读懂如何使用MCP创建服务器

如果你对MCP&#xff08;模型上下文协议&#xff09;一窍不通&#xff0c;在阅读本篇文章之前&#xff08;在获得对MCP深度认识之前&#xff09;&#xff0c;你可以理解为学习MCP就是在学习一个python工具库mcp&#xff0c;类似于其它python工具库一样&#xff0c;如numpy、sys…...