实测测试数据生成的可复现性:Random / SplittableRandom / L64X128MixRandom / shuffle 的同种子序列在 JDK 17、21、27 上逐字相同;ThreadLocalRandom 不能设种子;8 线程共享 Random 每次各线程拿到不同的值;并行流里共享 Random 的结果每次不同,按下标派生种子则完全一致;enum 的身份哈希作种子在 JDK 之间不同。
实测模块边界:未导出的 impl 包在 javac 阶段报 package impl is not visible,同样代码放进 classpath 就没有边界;反射调用要 exports,读私有字段要 opens;--patch-module 的同模块测试能访问 impl 而独立测试模块不能;ArchUnit 在 classpath 上抓到 1 个直接引用,但看不到 Class.forName 的字符串。
在真实 PostgreSQL 16.15 与 Java 序列化上实测回滚:8 种迁移里改名、删列、NOT NULL 无默认值会让 v1 的语句失败;down 迁移让 pending / banned 变成 unknown,DROP COLUMN 后再升级丢掉 3 行 email;序列化的字段在 v1 往返后被静默丢弃;滚动窗口只写新列时 v1 看到 100 行 NULL。
实测 SynchronousQueue:容量 0,offer 无人等待立即 false,put 阻塞时 size / peek / iterator 都看不到元素;newCachedThreadPool 的 50 个阻塞任务得到 50 个线程,ThreadPoolExecutor(2, 4) 在第 5 个任务拒绝;非公平模式是栈([5, 4, 3, 2, 1]);每个对象交接约 2.6 µs,比有缓冲队列的 0.12–0.14 µs 高约 20 倍。
实测 LinkedTransferQueue:tryTransfer 没有消费者就失败且不入队,transfer 会等到该元素自己被取走(前面 3 个元素也要先被取走);慢消费者下 put 1 秒积压 17,978,953 个、transfer 积压 1;size() 是 O(n)(100 万个约 1316 µs);1 对生产消费时比 LinkedBlockingQueue 快,4 对时慢 2 倍多。
实测 DelayQueue:poll 只返回已到期元素而 size / isEmpty / peek 包含未到期的;compareTo 与到期时间不一致时 B 被挡在 A 后面晚了约 1900 ms;到期后取到的延迟 p50 约 0.34 ms、p99 约 5–8 ms;4 个消费者只有 1 个取到元素;remove(Object) 随长度线性增长(10 万个约 31788 ns)。
实测 PriorityBlockingQueue:12 个相同优先级的任务出队顺序是 [t0, t11, …, t1];toString / stream 是堆数组顺序;入队后修改优先级不会重新排序;持续高优先级到达时低优先级 3 秒内饥饿,按创建时间老化后 2224 ms 被取到;无界队列在 -Xmx64m 放入 62809 个元素后 OOM,Semaphore 限界后稳定在 1000。
在 JDK 21 上实测 ExecutorService.close():它等价于 shutdown + 等待终止(909 ms),被中断时改为 shutdownNow;ForkJoinPool.commonPool().close() 什么也不等;ScheduledThreadPoolExecutor.close() 会等延迟任务(1147 ms)、取消周期任务;shutdownNow() 对不响应中断的任务没有效果;JDK 17 无法编译。
在 JDK 21 上实测 ThreadFactory 决定的线程身份:new Thread 继承创建者的 daemon / 优先级而 defaultThreadFactory 不继承;submit 抛异常不进入 UncaughtExceptionHandler,execute 抛异常会换线程;池线程拍下首次提交者的 context ClassLoader 与 InheritableThreadLocal;非 daemon 池让 JVM 5 秒不退出;线程是惰性创建的(0 → 1 → 2 → 2 → 2 → 3 → 4)。
在 JDK 21 上实测 CompletableFuture 的异常:同一个异常在 handle / join / get / exceptionally 里的形状(CompletionException、ExecutionException、原始异常)不同;没人观察的异常不产生任何输出;whenComplete 里再抛的异常被丢掉;allOf 在 100 ms 失败后仍等到 1006 ms 才抛出;cancel 与 orTimeout 不会停止底层任务。
用 GraalVM CE 25.0.2 的同一个 JDK 比较 C1 / C2 / Graal JIT:分支内逃逸的对象 C2 与 Graal 都被消除、关掉 PEA 后 Graal 不再消除;原以为 Graal 能消除的“同一对象罕见分支逃逸”两者都没消除;5 个小负载里 C2 有 4 个更快;稳态 stream 每批 24 ms vs 31 ms;峰值内存 205 vs 250 MiB。
用 GraalVM CE 25.0.2 的 native-image 实测:Hello 构建约 15.8 s、可执行文件 12.3 MiB,启动 5 ms vs JVM 40 ms、内存 9.3 vs 99.6 MiB;反射需要登记(agent 生成配置),未登记的类 ClassNotFoundException;--initialize-at-build-time 把静态状态冻结进镜像;吞吐上 stream 只有 JIT 的 1/3–1/4,hash 反而最快。