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

Sealed Class 与反射:运行时如何看到允许的子类型

用反射、javap 与故意制造的错误看 sealed:getPermittedSubclasses() 读 class 文件里的 PermittedSubclasses 属性;javac 与 JVM 两层检查(IncompatibleClassChangeError);只重编译一部分后旧 switch 遇到新子类抛 MatchException。

Java sealed 反射 PermittedSubclasses switch 真实验证 动画演示
Java 内部原理 2026-10-03

Switch 模式匹配:让分支覆盖范围可检查

验证 Java 21 的模式 switch:没有 case null 时 null 抛 NPE;守卫按顺序求值、类型不符的分支不执行守卫;record 模式嵌套解构,访问器异常包装成 MatchException;被支配分支与不穷尽的编译错误;字节码是 invokedynamic typeSwitch。

Java switch 模式匹配 record sealed 真实验证 动画演示
Java 内部原理 2026-10-03

注解处理器:在编译期生成代码与诊断

写一个真实的注解处理器(生成 Builder 类)并用 javac 运行:Filer 生成源文件,处理分 3 轮(第 2 轮处理新生成的源文件),Messager 的 ERROR/WARNING 带元素位置,-Werror、-proc:none/only/full 与 classpath 上的 services 文件在 JDK 21 的表现。

Java 注解处理器 javac Filer Messager 真实验证 动画演示
Java 内部原理 2026-10-03

多版本 JAR:同一坐标适配不同 Java 版本

用 jar 工具与 Maven 打多版本 JAR 并在 JDK 17、21、27 上运行:同一个 jar 在不同 JDK 上取不同版本的实现;没有 Multi-Release: true 或 -Djdk.util.jar.enableMultiRelease=false 时只用 base;jar 工具会拒绝公共 API 不一致的版本类。

Java 多版本JAR Multi-Release Maven jar 真实验证 动画演示
Java 内部原理 2026-10-03

Class-File API:用结构化方式生成和转换字节码

在 JDK 27 上用 java.lang.classfile 解析、从零生成和转换 class 文件:列出指令与代码元素;生成含分支的方法并自动带 StackMapTable;给每个方法入口插入 println(467 → 669 字节);DROP_STACK_MAPS 导致 VerifyError;JDK 21 没有这个包。

Java Class-File API 字节码 java.lang.classfile JDK 27 真实验证 动画演示
Java 内部原理 2026-10-03

Phaser:可动态加入的分阶段协作器

真实运行 Phaser:onAdvance 在每个阶段结束时回调并可返回 true 终止(终止后阶段号为负数);运行中 register 与 arriveAndDeregister;超时与中断不会破坏 Phaser(CyclicBarrier 会 isBroken);64 线程下平铺与分层每轮 178.7 vs 177.8 μs,没有可测量差别。

Java Phaser 并发 同步器 CyclicBarrier 真实验证 动画演示
Java 内部原理 2026-10-03

Exchanger:两个线程如何交换中间结果

真实运行 Exchanger:两个线程同时返回并互换对象引用;超时与中断后可继续使用;多线程共用时两两配对,奇数个会有一个落单;交换 1024 元素缓冲区传 2048 万个 int 每轮 13–56 ms,逐个元素的 LinkedBlockingQueue 约 1950 ms。

Java Exchanger 并发 同步器 缓冲区交换 真实验证 动画演示
Java 内部原理 2026-10-03

LockSupport:park 与 unpark 的许可模型

真实运行 LockSupport:许可最多一个、不累加,先 unpark 再 park 立刻返回,而先 notify 再 wait 会丢通知;unpark 到 park 返回中位 1.9 μs;park 遇到中断标志立刻返回,错误的循环写法 200 ms 空转 3239916 次;用 park/unpark 写一个 FIFO 互斥锁并与公平 ReentrantLock 对比。

Java LockSupport park unpark 并发 真实验证 动画演示
Java 内部原理 2026-10-03

AQS 自定义同步器:从状态位到等待队列

用 AbstractQueuedSynchronizer 写不可重入互斥锁、信号量、闩锁和带 Condition 的有界缓冲区并运行验证:共享模式一次释放唤醒所有等待者;非公平与公平 tryAcquire 的吞吐 155,738,178 对 155,738,178;await 完全释放锁、signal 把线程移到锁的等待队列。

Java AQS AbstractQueuedSynchronizer 并发 同步器 真实验证 动画演示
Java 内部原理 2026-10-03

ManagedBlocker:让 ForkJoinPool 正确处理阻塞

真实运行 ForkJoinPool.managedBlock:16 个阻塞 100 ms 的任务普通阻塞 432 ms、managedBlock 110 ms(线程 17);maximumPoolSize 小于需要时 managedBlock 抛 RejectedExecutionException;CompletableFuture.join、Phaser、CyclicBarrier、LinkedBlockingQueue.take 会补偿,CountDownLatch、Semaphore、ReentrantLock 不会。

Java ForkJoinPool ManagedBlocker 并发 真实验证 动画演示
Java 内部原理 2026-10-03

ThreadLocal 与类加载器泄漏:线程池为什么会留住旧应用

用 WeakReference 验证 ThreadLocal 导致的类加载器泄漏:值是插件类的实例时线程池线程活着就不能回收,值是 String 或卸载前 remove() 就能回收;过期条目的 40 MB 在 GC 后仍占 42 MB 直到被清理;InheritableThreadLocal 在池线程复用时看到旧值。

Java ThreadLocal 类加载器 内存泄漏 线程池 真实验证 动画演示
Java 内部原理 2026-10-03

并发容器的弱一致性:遍历时看到的到底是什么

真实验证并发容器的弱一致性:遍历时修改 ArrayList/HashMap 抛 CME 而并发容器不抛;并发写入时 ConcurrentHashMap 的遍历数到的条目数在 -1000 到 1048 之间,size() 却始终合理;转账求和有 79% 的读取不一致;CopyOnWriteArrayList 是快照但 add 随大小线性变慢。

Java 并发容器 弱一致性 ConcurrentHashMap CopyOnWriteArrayList 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号