如何使用 static 静态代码块在类加载阶段初始化耗时的重量级资源

夏强姑娘_1690

夏强姑娘_1690

2026-04-14

863人浏览

原创

静态代码块不适合放耗时操作,因其在jvm类初始化阶段单线程阻塞执行,失败会导致exceptionininitializererror使类不可用;应改用静态内部类懒加载、@postconstruct或spring bean生命周期管理。

如何使用 static 静态代码块在类加载阶段初始化耗时的重量级资源

不能直接在 static 代码块里初始化耗时的重量级资源——这么做会阻塞类加载,拖慢整个应用启动,甚至引发超时或 NoClassDefFoundError。

为什么 static 块不适合放耗时操作

静态代码块在 JVM 类初始化阶段(<clinit></clinit> 方法)执行,该阶段是单线程、阻塞式、不可中断的。一旦里面包含网络请求、大文件读取、数据库连接池初始化等操作:

  • 所有后续对该类或其子类的首次访问都会被卡住,直到它完成
  • 若失败(如配置文件缺失、服务未就绪),抛出 ExceptionInInitializerError,导致该类永远无法使用
  • Spring 等框架在扫描或代理时可能触发类加载,意外拖垮启动流程

替代方案:用静态内部类实现懒加载(Initialization-on-demand holder)

这是最轻量、线程安全、且不污染主类加载时机的方案。核心是把重量级资源封装进一个静态内部类,利用 JVM 对静态内部类“首次主动使用才初始化”的规则延迟执行。

示例:

public class HeavyResourceHolder {
    private static class LazyLoader {
        static final HeavyResource INSTANCE = new HeavyResource();
    }

    public static HeavyResource getInstance() {
        return LazyLoader.INSTANCE;
    }
}

关键点:

  • LazyLoader 类本身不会在 HeavyResourceHolder 加载时初始化
  • 只有第一次调用 getInstance() 时,JVM 才触发 LazyLoader 的初始化,此时才执行 new HeavyResource()
  • 整个过程由 JVM 保证线程安全,无需 synchronized 或双重检查锁

如果必须用 static 块,至少加兜底保护

极少数场景(如遗留系统强约束)不得不放在 static 块中,务必做三件事:

  • 用 try-catch 包裹全部逻辑,捕获 Throwable(不只是 Exception),避免 ExceptionInInitializerError 泄露
  • 设置超时控制:对 I/O 操作用 ExecutorService + Future.get(3, TimeUnit.SECONDS),超时则 fallback 到默认值或抛运行时异常
  • 记录明确日志:包括开始时间、耗时、是否成功,方便排查启动慢问题

错误示范:static { loadConfigFromRemote(); };正确思路:static { initWithTimeout(); }

Spring 环境下优先走 Bean 生命周期

如果你在 Spring 管理的上下文中,完全没必要手写 static 块。改用:

  • @PostConstruct 注解方法:在依赖注入完成后、Bean 可用前执行
  • @Bean(initMethod = "init"):显式指定初始化方法,支持异常传播和重试逻辑
  • InitializingBean 接口:虽已过时,但语义清晰,适合简单场景

这些方式可被 Spring 容器统一管理生命周期、参与事务、支持 AOP,并能优雅处理失败(如标记 Bean 创建失败,而非让整个 Class 初始化崩溃)。

真正容易被忽略的是类加载器隔离带来的“多次执行”假象:同一个类被不同 ClassLoader 加载(如 Web 应用热部署、OSGi、模块化 JDK),静态块会各执行一次。别把它当成“全局唯一”,而要按实际类加载上下文来设计初始化边界。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

11197

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

8322

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

7172

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1204

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

968

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1436

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2949

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

20211

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1295

8

热门下载

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

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.9万人学习