知其然,知其所以然
Java 内部原理 2026-10-03

JOL 对象布局:看到对象头和对齐填充

用 JOL 0.17 看 JDK 21 对象布局:12 字节头、字段重排与填充、数组头 16 字节、选项对布局的影响、集合的每元素字节数;并用 500 万个实例实测堆占用核对;JDK 27 默认使用 8 字节紧凑对象头,Q{int x;int y} 实测少 8 字节。

Java JOL 对象布局 对象头 压缩指针 紧凑对象头 真实验证 动画演示
Java 内部原理 2026-10-03

Template Interpreter:解释器如何执行字节码

用 -XX:+PrintInterpreter 看 HotSpot 模板解释器:81K 机器码、275 个 codelet、每个字节码一个;用 llvm-mc 反汇编 iadd(8 个指令字,以 br 间接跳转分发);-Xint 每字节码约 0.44 ns,比编译慢约 14 倍;PrintCompilation 找到调用 200 次、回边 60000 次的阈值边界及 128/1024 的检查点。

Java 模板解释器 字节码 分层编译 PrintInterpreter 真实验证 动画演示
Java 内部原理 2026-10-03

常量池解析:符号引用何时变成直接引用

真实验证常量池解析:没走到的分支里的类不会加载;验证器为了检查赋值兼容会提前加载 LazySub 与 Base 但不加载接口实现;解析失败每次抛新的 NoClassDefFoundError;76 个常量池条目的构成;字符串字面量驻留;每个 lambda 调用点一个类。

Java 常量池 类解析 惰性加载 字符串驻留 invokedynamic 真实验证 动画演示
Java 内部原理 2026-10-03

Foreign Function & Memory API:安全地访问 native

在 JDK 21(预览)与 JDK 27 上真实验证 FFM API:直接调 libc 的 getpid / strlen / qsort(带 Java 上行调用),用自己 clang 编出的动态库验证 C 结构体与 MemoryLayout 的大小与偏移一致,各种内存错误的异常,以及两个版本之间 API 与异常的差异。

Java FFM Foreign Function Memory API Linker MemorySegment 真实验证 动画演示
Java 内部原理 2026-10-03

Arena 与 MemorySegment:堆外资源如何成组释放

在 JDK 27 上真实验证 Arena 与 MemorySegment:四种 Arena 的关闭规则、分配时的清零与对齐、3 GB 段的 RSS 与 2 GB 限制、批量操作与堆段的限制、内存映射文件的读写。

Java Arena MemorySegment 堆外内存 内存映射 FFM 真实验证 动画演示
Java 内部原理 2026-10-03

Linker:Java 如何描述 native 函数签名

在 JDK 27 上用自己编的 C 库验证 Linker:结构体按值传入与返回(16/8/32 字节)、变参函数必须声明 firstVariadicArg(否则输出乱码)、捕获 errno、critical 调用省约 1.2 ns、上行调用的类型检查、上行调用里抛异常会让 JVM 直接退出。

Java Linker FFM 结构体 变参 errno upcall 真实验证 动画演示
Java 内部原理 2026-10-03

JNI 与 Panama:两种 native 边界的取舍

在 JDK 27 上用自己 clang 编的 JNI 库与 Panama downcall 对比:add 调用 JNI 3.73 ns,Panama 局部句柄 6.69 ns、static final 句柄 4.51 ns、加 critical 3.59 ns;小数组 Panama 比 JNI 复制快一个量级;大数组各种传法都落在 C 循环本身的时间。

Java JNI Panama FFM 性能 真实验证 动画演示
Java 内部原理 2026-10-03

JMH 基准测试误区

用 JMH 1.37 真实演示基准陷阱:丢弃结果的 sqrt 与空方法一样 0.3 ns、常量输入被折叠、1000 次循环不是单次的 1000 倍、不逃逸的分配被消除;手写 nanoTime 计时在不同批次里从 10500 ns 降到 8.89 ns,与 JMH 的 4.95 ns 也不同。

Java JMH 基准测试 死代码消除 常量折叠 逃逸分析 真实验证 动画演示
Java 内部原理 2026-10-03

JMH Blackhole:如何保留基准中的计算结果

在 JDK 21 上用 JMH 1.37 比较 Blackhole 的三种模式:compiler 下 consume 与 return 都是 0.590 ns/op,full 是 1.106、FULL_DONTINLINE 是 1.929;丢弃结果的计算在所有模式下被删除;consumeCPU 的耗时(1 token 2.291 ns 到 1000 tokens 1705 ns)。

Java JMH Blackhole 基准测试 consumeCPU 真实验证 动画演示
Java 内部原理 2026-10-03

JMH 预热与 Fork:为什么要启动多个 JVM

用 JMH 1.37 真实验证为什么要 fork:共用同一个方法的单态基准在多态基准之后(-f 0)慢 4.6 倍(2042.844 对 447.592 ns/op),-f 1 则没有;预热在 1 秒迭代里几乎看不出、在 10 毫秒迭代里第 1 次慢 40%;5 个 fork 之间的差异在 2% 以内。

Java JMH 预热 fork 类型profile污染 基准测试 真实验证 动画演示
Java 内部原理 2026-10-03

jcstress:验证并发交错下的可见结果

用 jcstress 0.16 在本机(Apple Silicon)真实观察:Store Buffering 普通字段下 (0,0) 出现 24,354,555 次、volatile 下 0 次;Message Passing 在普通字段下观察到 1,723 次重排序、release/acquire 下 0 次;c++ 丢失更新 28,385,172 次、AtomicInteger 0 次;long 没有撕裂。

Java jcstress 并发测试 内存模型 重排序 真实验证 动画演示
Java 内部原理 2026-10-03

CPU Cache Line:Java 代码如何触发缓存一致性

在 Apple Silicon 上真实测量缓存的影响:sysctl 报告缓存行 128 字节,步长遍历在步长 32(128 字节)才进入每次访问约 3.5 ns 的平台;二维数组按列遍历比按行慢 4.7 倍;随机依赖读延迟在 128 KB 与 256 KB 之间、8 MB 与 32 MB 之间出现台阶,与 L1 / L2 容量一致。

Java CPU缓存 缓存行 空间局部性 步长访问 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号