知其然,知其所以然
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 真实验证 动画演示
Java 内部原理 2026-10-03

Safepoint:所有线程为什么会短暂停下来

用 -Xlog:safepoint 看 JDK 21 的安全点:一个小程序 25 次安全点,到达安全点通常只要几微秒;去掉计数循环里的安全点检查后 Thread.getAllStackTraces() 从 0 ms 变成约 1100 ms、System.gc() 变成 1066 ms;getThreadInfo 也是全局安全点;空闲 JVM 没有周期性安全点。

Java Safepoint 安全点 JIT GC日志 真实验证 动画演示
Java 内部原理 2026-10-03

TLAB:线程如何快速分配小对象

用 -Xlog:gc+tlab=trace 和分配基准看 TLAB:有 TLAB 时 1/8 线程的小对象分配 194/596 M 对象/秒,-XX:-UseTLAB 只有 13/3;TLAB 随线程数自适应变小;-XX:TLABSize=64k 使吞吐降到 132 M/秒;TLABSize=4m 被 JVM 拒绝。

Java TLAB 对象分配 JVM调优 真实验证 动画演示
Java 内部原理 2026-10-03

逃逸分析:对象什么时候可以不进堆

用每次迭代分配的字节数验证 C2 逃逸分析:不逃逸的 24 字节对象默认 ≈0 字节而关闭 EA 后 24 字节;只在 1/1024 的路径上逃逸就消除不了;大方法、int[100]、List 迭代器、Optional 链没被消除;局部装箱、StringBuilder、锁被消除。

Java 逃逸分析 标量替换 JIT 锁消除 真实验证 动画演示
Java 内部原理 2026-10-03

Compressed Oops:对象引用为什么可以用更少位数

验证压缩指针:-Xmx 到 31900m 默认开启、32g 起关闭,对象对齐 16 时上限 64g;对象大小开启与关闭对比(Node 32/40/48 字节);500 万个节点堆占用 155 MB 对 194 MB;JDK 27 默认紧凑对象头使 new Object() 只有 8 字节、堆占用 117 MB。

Java Compressed Oops 压缩指针 对象头 内存占用 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号