用反射、javap 与故意制造的错误看 sealed:getPermittedSubclasses() 读 class 文件里的 PermittedSubclasses 属性;javac 与 JVM 两层检查(IncompatibleClassChangeError);只重编译一部分后旧 switch 遇到新子类抛 MatchException。
验证 Java 21 的模式 switch:没有 case null 时 null 抛 NPE;守卫按顺序求值、类型不符的分支不执行守卫;record 模式嵌套解构,访问器异常包装成 MatchException;被支配分支与不穷尽的编译错误;字节码是 invokedynamic typeSwitch。
写一个真实的注解处理器(生成 Builder 类)并用 javac 运行:Filer 生成源文件,处理分 3 轮(第 2 轮处理新生成的源文件),Messager 的 ERROR/WARNING 带元素位置,-Werror、-proc:none/only/full 与 classpath 上的 services 文件在 JDK 21 的表现。
用 jar 工具与 Maven 打多版本 JAR 并在 JDK 17、21、27 上运行:同一个 jar 在不同 JDK 上取不同版本的实现;没有 Multi-Release: true 或 -Djdk.util.jar.enableMultiRelease=false 时只用 base;jar 工具会拒绝公共 API 不一致的版本类。
在 JDK 27 上用 java.lang.classfile 解析、从零生成和转换 class 文件:列出指令与代码元素;生成含分支的方法并自动带 StackMapTable;给每个方法入口插入 println(467 → 669 字节);DROP_STACK_MAPS 导致 VerifyError;JDK 21 没有这个包。
真实运行 Phaser:onAdvance 在每个阶段结束时回调并可返回 true 终止(终止后阶段号为负数);运行中 register 与 arriveAndDeregister;超时与中断不会破坏 Phaser(CyclicBarrier 会 isBroken);64 线程下平铺与分层每轮 178.7 vs 177.8 μs,没有可测量差别。
真实运行 Exchanger:两个线程同时返回并互换对象引用;超时与中断后可继续使用;多线程共用时两两配对,奇数个会有一个落单;交换 1024 元素缓冲区传 2048 万个 int 每轮 13–56 ms,逐个元素的 LinkedBlockingQueue 约 1950 ms。
真实运行 LockSupport:许可最多一个、不累加,先 unpark 再 park 立刻返回,而先 notify 再 wait 会丢通知;unpark 到 park 返回中位 1.9 μs;park 遇到中断标志立刻返回,错误的循环写法 200 ms 空转 3239916 次;用 park/unpark 写一个 FIFO 互斥锁并与公平 ReentrantLock 对比。
用 AbstractQueuedSynchronizer 写不可重入互斥锁、信号量、闩锁和带 Condition 的有界缓冲区并运行验证:共享模式一次释放唤醒所有等待者;非公平与公平 tryAcquire 的吞吐 155,738,178 对 155,738,178;await 完全释放锁、signal 把线程移到锁的等待队列。
真实运行 ForkJoinPool.managedBlock:16 个阻塞 100 ms 的任务普通阻塞 432 ms、managedBlock 110 ms(线程 17);maximumPoolSize 小于需要时 managedBlock 抛 RejectedExecutionException;CompletableFuture.join、Phaser、CyclicBarrier、LinkedBlockingQueue.take 会补偿,CountDownLatch、Semaphore、ReentrantLock 不会。
用 WeakReference 验证 ThreadLocal 导致的类加载器泄漏:值是插件类的实例时线程池线程活着就不能回收,值是 String 或卸载前 remove() 就能回收;过期条目的 40 MB 在 GC 后仍占 42 MB 直到被清理;InheritableThreadLocal 在池线程复用时看到旧值。
真实验证并发容器的弱一致性:遍历时修改 ArrayList/HashMap 抛 CME 而并发容器不抛;并发写入时 ConcurrentHashMap 的遍历数到的条目数在 -1000 到 1048 之间,size() 却始终合理;转账求和有 79% 的读取不一致;CopyOnWriteArrayList 是快照但 add 随大小线性变慢。