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

HTTP/2:帧、流和多路复用

用 curl 与自己起的 nginx(h2)验证 HTTP/2:ALPN 协商 h2、伪头部;10 个并发请求 HTTP/2 用 1 个连接、HTTP/1.1 用 10 个;流编号是奇数递增 [1, 3, 5, 7]…;用 Netty 的 HPACK 编码器,相同请求头第 1 次 136 字节、之后 7 字节(HTTP/1.1 文本 190 字节)。

Java HTTP/2 多路复用 HPACK nginx 真实验证 动画演示
Java 内部原理 2026-10-02

DNS 缓存:Java 如何缓存域名解析

实测 JVM 的 DNS 缓存(JDK 21,真实公网域名):默认第一次解析 70.58 ms、缓存命中约 0.485 ms、t=31 s 过期,与 30 秒默认值一致;networkaddress.cache.ttl=2 与 0 的效果;对不存在的域名默认也有 10 秒的负缓存(t=9 s 命中、t=11 s 过期)。

Java DNS 缓存 InetAddress networkaddress.cache.ttl 真实验证 动画演示
Java 内部原理 2026-10-02

URLClassLoader:插件系统如何动态加载 JAR

用真实的插件 jar 验证 URLClassLoader:接口由父加载器共享、插件类只在自己的加载器里;jar 自带接口且父加载器为 null 时 ClassCastException;两个加载器加载同一个 jar 得到不同的类;close() 释放文件描述符,引用清空后 GC 能卸载;插件起了线程时卸载不掉。

Java URLClassLoader 插件 类加载器 类卸载 真实验证 动画演示
Java 内部原理 2026-10-02

Module Layer:运行时如何创建隔离模块层

验证 ModuleLayer:启动层不含 greeter,新层的父层是 boot、有自己的类加载器;同一个 JVM 里同时运行 greeter 的 v1 与 v2(两个不同的 greet.Greeter 类);层内模块仍遵守 exports,ServiceLoader 可限定到某一层;重复创建得到不同的 Module,解析缺失模块抛 FindException。

Java 模块系统 ModuleLayer 隔离 真实验证 动画演示
Java 内部原理 2026-10-02

Java Instrumentation:在类加载时插入观测逻辑

用 -javaagent 实测 Instrumentation:premain 在 main 之前执行、此时已加载 809 个类、transformer 只被新加载的 6 个类调用;用 ASM 在 demo.Target 的方法入口出口插入计时(1795 µs 与 86 µs);transformer 抛异常没有任何输出、类按原样加载。

Java Instrumentation Java Agent ASM 真实验证 动画演示
Java 内部原理 2026-10-02

JVMTI:本地诊断接口能观察什么

用 clang 编译一个真实的 JVMTI C agent:申请能力成功(可申请 68 项)、通过事件回调统计 ClassPrepare 172、ThreadStart 5、GC 9 次;VMDeath 时 GetLoadedClasses 661 个类、IterateOverInstancesOfClass 数出 app.Foo 1234 个实例、列出 6 个线程及状态。

Java JVMTI 本地诊断 C 语言 Agent 真实验证 动画演示
Java 内部原理 2026-09-23

递归lambda真实验证:连静态字段自引用都编译不过,必须靠一层间接引用

真实验证局部变量lambda直接自引用真实编译失败(variable fib might not have been initialized);真实意外发现连static字段在同一条语句里自引用也真实编译失败(self-reference in initializer);真实验证数组包装、静态字段分两步赋值、具名方法引用三种写法都能正确实现递归。

Java Lambda 函数式接口 动画演示
Java 内部原理 2026-09-22

实例初始化块真实验证:执行顺序真实是父类块→父类字段→父类构造器→子类块→子类字段→子类构造器

真实记录Derived继承Base,各自都有实例初始化块、字段初始化、构造器时的真实完整执行顺序;真实验证同一个类里多个初始化块和字段初始化真实严格按源码书写顺序交替执行。

Java 类初始化 继承 动画演示
Java 内部原理 2026-09-21

AtomicReference真实复现ABA问题:值改回来了,CAS真实浑然不知

真实用两个线程复现ABA问题:threadA把AtomicReference<Integer>的值从100改成50再改回100,threadB用最初读到的100做CAS(999)真实依然成功;真实意外发现超出Integer缓存范围时单线程内CAS都会因自动装箱产生不同对象实例而真实失败;真实验证AtomicStampedReference靠版本戳真正解决了ABA问题。

Java 并发 CAS 动画演示
Java 内部原理 2026-09-20

Lock+Condition真实验证:同一把锁开两个Condition,signal真实只唤醒对应的那一组

真实用一个ReentrantLock创建notEmpty和notFull两个独立Condition,各挂起5个等待线程;真实调用notEmpty.signalAll()后,notEmpty组真实全部被唤醒(5),notFull组真实一个都没动(0);真实验证未持有锁时调用Condition.await()真实抛出IllegalMonitorStateException。

Java 并发 Lock 动画演示
Java 内部原理 2026-09-19

ThreadLocalRandom真实验证:并发场景下真实快了184倍

真实用8线程各调用500万次nextInt(),共享一个Random实例真实耗时7935ms,改用ThreadLocalRandom.current()真实只要43ms,真实快184.53倍;真实验证同一线程内两次ThreadLocalRandom.current()调用返回同一个实例,不同线程各自拿到独立、不需要竞争的随机数生成器。

Java 并发 性能 动画演示
Java 内部原理 2026-09-18

Arrays.fill()真实陷阱:填充二维数组的每一行,真实变成了同一个数组的三个引用

真实验证Arrays.fill(int[][] arr2d, int[] sharedRow)这个合法调用真实把每一行都指向同一个数组对象,不是三个独立副本;真实修改arr2d[0][0]后,其余两行真实一起被改变;真实对比正确写法(for循环对每行单独调用Arrays.fill)才能得到三个真正独立的行数组。

Java 数组 陷阱 动画演示
京ICP备2026067502号-1京公网安备11010502063487号