0

0

详解Java中的类初始化死锁风险_静态代码块中的线程交互禁忌

P粉602998670

P粉602998670

发布时间:2026-02-28 08:56:40

|

434人浏览过

|

来源于php中文网

原创

静态代码块调用外部同步方法会因类初始化锁导致死锁。jvm对每个类加隐式initialization lock,若a类静态块调用b类方法而b又依赖a,则两线程互相等待clinit锁,造成启动卡住。

详解java中的类初始化死锁风险_静态代码块中的线程交互禁忌

静态代码块里调用外部同步方法,为什么一启动就卡住?

Java 类初始化阶段可能被多个线程并发触发,而 JVM 会强制对每个类加一个隐式的 initialization lock。一旦某个线程在静态代码块中阻塞(比如等待另一个类完成初始化),又恰好那个类也在等当前类——死锁就成立了。

这不是理论风险,是真实发生的典型场景:比如 A.class 的静态块里调用了 B.doSomething(),而 B.class 的静态块又反向依赖 A.SOME_CONSTANT

  • JVM 规范要求类初始化必须串行化,但不保证跨类顺序,只靠“首次主动使用”触发
  • 哪怕你没显式开线程,ClassLoader.loadClass()Class.forName() 或反射访问静态字段都可能触发初始化
  • 常见错误现象:Thread.getState() == BLOCKED 且堆栈停在 java.lang.Class.forName 或静态块某行,jstack 显示两个线程互相等待对方的 initialization lock

如何快速定位哪个类在初始化时互相等待?

别猜,直接看线程快照。关键不是找“死锁”字样,而是找处于 CLINIT 状态的线程(即正在执行 <clinit></clinit> 方法)以及它们阻塞在哪个类上。

  • jstack -l <pid></pid> 抓取线程 dump,搜索 java.lang.Thread.State: BLOCKED (on object monitor)at java.lang.Class.forNameat <clinit></clinit>
  • 重点关注堆栈里连续出现的两个类,比如线程1卡在 A.<clinit></clinit> 等待 B.class,线程2卡在 B.<clinit></clinit> 等待 A.class
  • IDE 调试时,在静态块第一行设断点,然后用 Ctrl+Break(Windows)或 kill -3(Linux/macOS)触发线程 dump,比单步更可靠

static final 字段初始化顺序,为什么不能靠写法“控制”?

很多人以为把 A 的静态字段写在 B 前面,或者用 static {} 块手动排序就能避免问题——不行。JVM 不按源码顺序初始化类,只按“首次主动使用”的时机决定谁先触发。

Logo Galleria
Logo Galleria

免费在线AI Logo生成工具,打造定制Logo

下载

立即学习Java免费学习笔记(深入)”;

  • static final int X = B.Y + 1; 这种写法,会强制先触发 B 初始化;但如果 B 又引用了 A.X,就构成循环依赖
  • 编译期常量(如 static final int X = 42;)会被内联,不触发初始化;但只要涉及方法调用、非编译期常量表达式,就会触发
  • 工具类如 Objects.requireNonNull()Logger.getLogger() 在静态块里调用,也可能间接触发其他类初始化(比如 Logger 初始化时加载 Handler 子类)

安全替代方案:延迟到第一次使用再初始化

把静态资源从类加载期挪到运行期,彻底绕过 <clinit></clinit> 阶段的锁竞争。核心思路是用“懒汉式 + volatile + double-check”或 Holder 模式,而不是在 static 块里硬扛。

  • 推荐 Holder 模式:定义私有静态内部类 private static class Holder { static final A INSTANCE = new A(); },首次调用 Holder.INSTANCE 才触发初始化,且由 JVM 保证线程安全
  • 避免在静态块中做任何可能触发其他类初始化的操作:不要调用非本类的静态方法、不要访问其他类的静态字段、不要 new 其他类实例(除非确定该类无静态初始化逻辑)
  • 如果必须预热资源,改用显式初始化方法,比如 public static void init() { ... },由应用启动流程统一调用,而非依赖类加载自动触发

最麻烦的不是写错,是错得悄无声息——程序在单线程下永远正常,一上生产环境并发加载就偶发挂起。初始化顺序不是靠经验猜出来的,得靠线程 dump 说话。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1560

2023.10.24

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1560

2023.10.24

java中break的作用
java中break的作用

本专题整合了java中break的用法教程,阅读专题下面的文章了解更多详细内容。

120

2025.10.15

java break和continue
java break和continue

本专题整合了java break和continue的区别相关内容,阅读专题下面的文章了解更多详细内容。

260

2025.10.24

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

870

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

592

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

294

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

210

2025.08.29

Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

0

2026.02.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3.9万人学习

C# 教程
C# 教程

共94课时 | 10.3万人学习

Java 教程
Java 教程

共578课时 | 73.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号