一个 class 文件是怎么变成可执行的类的?这篇用 -Xlog:class+load 和几段小程序,把「什么时候加载、什么时候初始化、什么时候报错」逐项量出来,不靠背。
[加载] Main source: file:<jtmp>/j1a/out/
step 1: main 开始
step 2: 即将 new Lazy()
[加载] Main$Lazy source: file:<jtmp>/j1a/out/
[Lazy 静态块执行]
Lazy.hi()
step 3: 结束这是 Java 系列的新一批(接在已有的 140 篇之后)的第一篇;下一篇:synchronized:从对象锁到字节码监视器。
A: Class.forName("Main$T", false, cl)
返回了 Main$T
B: cl.loadClass("Main$T")
返回了
C: T.class 字面量
得到 T
D: new T()
[T 静态块执行]
完成 1) 调用 viaSameType(false)(分支没走到)
正常返回
2) 调用 viaSameType(true)(走到 new Dep())
java.lang.NoClassDefFoundError: Dep
3) 调用 Holder.m(false)(分支没走到,但方法里有 use(new Dep()),参数类型是 Base)
java.lang.NoClassDefFoundError: Dep默认(JDK 自带 CDS 归档) 加载 445 个类:来自归档 441、来自 jrt 模块文件 3;整个进程中位耗时 27 ms -Xshare:off 加载 480 个类:来自归档 0、来自 jrt 模块文件 479;整个进程中位耗时 42 ms
java.lang.String → null(启动类加载器) java.sql.Driver → platform / jdk.internal.loader.ClassLoaders$PlatformClassLoader Main → app / jdk.internal.loader.ClassLoaders$AppClassLoader