Java 类装入器是否保证不装入未使用的类?

2022-09-04 21:00:20

是否可以保证(默认的系统)Java 类装入器不会尝试装入正在运行的代码中未引用的类?举几个例子来说明我的意思:

  • 我正在使用一个我知道包含对另一个类的引用,但我只使用框架中不包含这些引用的部分。省略是否安全?framework.jarlibrary.jarlibrary.jar
  • 静态块在首次装入类时运行。如果没有正在运行的代码包含对特定类的引用,是否确定它的静态块未运行?

快速测试它似乎像上面假设的那样工作,无论如何加载未使用的类都没有多大意义,但是对此有什么保证吗?

加法:似乎我上面的“静态块在首次加载类时运行”语句有些不正确。绝对可以在不运行类(另一件事)的情况下加载它们(一件事)。所以我对这两种情况都感兴趣;保证类不会加载,也不会运行


答案 1

没有这样的保证1 wrt 加载类。

但是,可以保证静态块不会过早运行。触发类初始化的事件在 JLS 12.4.1 中指定。

类或接口类型 T 将在首次出现以下任一项之前立即初始化:

  • T 是一个类,并创建了 T 的一个实例。
  • T 是一个类,调用由 T 声明的静态方法。
  • 分配由 T 声明的静态字段。
  • 使用 T 声明的静态字段,并且该字段不是常量变量 (§4.12.4)。
  • T 是顶级类,并执行词法嵌套在 T 中的断言语句 (§14.10)。

1 - 观察到当前一代Java实现不会不必要地加载类,但这并不能保证。唯一的保证是它在官方规范中写的内容。


答案 2

Java 规范声明

装入过程由类 ClassLoader 及其子类实现。ClassLoader 的不同子类可能实现不同的加载策略。特别是,类装入器可以高速缓存类和接口的二进制表示形式,根据预期用法预取它们,或者将一组相关类装入在一起。

因此,类装入器可以自由地预取类文件。

类或接口类型 T 将在首次出现以下任一项之前立即初始化:

  • T 是一个类,并创建了 T 的一个实例。
  • T 是一个类,调用由 T 声明的静态方法。
  • 分配由 T 声明的静态字段。
  • 使用 T 声明的静态字段,并且对该字段的引用不是编译时常量 (§15.28)。对编译时常量的引用必须在编译时解析为编译时常量值的副本,因此使用此类字段永远不会导致初始化。

静态块仅在首次使用该类时执行。


推荐