{
 "date": "2026-10-25",
 "timezone": "Asia/Shanghai",
 "issue": 44,
 "batch": "U07",
 "sourceTag": "OpenJDK jdk-17.0.12+7 (fixed mechanism source)",
 "environment": {
  "os": "macOS 26.7.1 (x86_64)",
  "architecture": "x86_64",
  "javaVersion": "java version \"17.0.12\" 2024-07-16 LTS\nJava(TM) SE Runtime Environment (build 17.0.12+8-LTS-286)",
  "javaHome": "/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home",
  "runtimeNote": "与 U05/U06 相同的本机 Oracle JDK 17.0.12+8（x86_64）。绿跑开始于 2026-10-24T17:28:50Z（北京时间 2026-10-25 01:28，证据文件名按票内工作日 2026-10-24 登记）。",
  "runPolicy": "每次运行由包装脚本设置 90 秒 perl alarm 上限、-Xmx128m、唯一 TMPDIR 并作为 java.io.tmpdir 传入；结束后检查私有目录剩余条目（实测 0）并定向删除。run.sh 自身 mktemp 唯一编译目录 + EXIT/INT/TERM trap。探针所有线程等待与 join 均有上限，线程池在 finally 关闭。",
  "stderrNote": "stderr 中 '注: TypeProbe.java 使用了未经检查或不安全的操作' 来自 run.sh jmm 编译阶段同目录既有 TypeProbe.java（run.sh 固定编译列表），非本票输出错误；'Picked up JAVA_TOOL_OPTIONS' 是 JVM 对显式内存/临时目录限制的回显。"
 },
 "tdd": {
  "redGreen": [
   "红1（ABA 误解断言，2026-10-24T17:24Z 前后）：先按常见误解写下断言『引用被移除过，陈旧 CAS 应失败、栈应保持 [A]』（/tmp/u07-red/JmmProbeRed.java 断言 drained==[A]），实跑 AssertionError: RED1 expected [A] (predicted stale CAS fails), got [B]，exit 1——CAS 只比较当前引用值，栈顶回到 a 即成功，已移除的 B 复活、A 丢失；修正断言为 [B] 后 exit 0。正文按此口径撰写损坏链。",
   "红2（数据竞争误解断言，2026-10-24T17:23Z 前后）：先断言『x86 缓存一致，普通 int 两线程各 10 万次不丢更新』（断言 plainFinal==200000），实跑 AssertionError: RED2 expected 200000, got 110558，exit 1；随后按『观察值非契约』口径改为仅记录普通结果、断言原子版本精确 200000，exit 0。",
   "红3（版本戳旧观察，2026-10-24T17:21Z 前后，开发中真实发生）：版本戳栈第一版在两次 CAS 后未重读当前戳就用作期望值，实跑 AssertionError: stamped stack corrupted: stamp=2，exit 1——恰是『用陈旧观察做 CAS 会失败』的教学点本身；修正为每次 CAS 前重读引用与戳后 exit 0。"
  ],
  "compileFixes": "前几轮为编译/逻辑修复（LongAdder 竞争计数漏写内层循环、COW 反射需 --add-opens、addIfAbsent 期望值按列表现状修正、异键写者耗时改为线程内自测、并发写者总数对齐 2005），属实验代码修正，不计入红绿。",
  "noFakeRed": "三个红均为先写下的真实预期被实测推翻，随后按源码/规范修正断言，不倒造 red。"
 },
 "runs": [
  {
   "name": "jmm-final",
   "command": [
    "bash",
    "labs/java-senior/run.sh",
    "jmm"
   ],
   "startedUtc": "2026-10-24T17:28:50+00:00",
   "timeoutSeconds": 90,
   "timedOut": false,
   "exit": 0,
   "stdout": "java.version=17.0.12 vm=Java HotSpot(TM) 64-Bit Server VM\n\n== 1. unsynchronized race: observation, then fix ==\nplain int final=124245 expected=200000 -> OBSERVE lost updates: 75755\nAtomicInteger final=200000 expected=200000\nPASS race: plain run recorded as observation; atomic run asserted exact\n\n== 2. stop flag: plain (may not reproduce) vs volatile ==\nplain flag never observed: hit spin limit（JIT 可把普通读提升出循环；JLS 不保证无同步可见，属允许结果）\nvolatile flag observed after 691571260 spins（volatile 写读建立 happens-before，断言通过）\nPASS stop flag: volatile asserted observed; plain recorded as observation\n\n== 3. final freeze: this-escape vs completed constructor ==\nduring construction (escape + latch ordering): final=0 plain=0（冻结发生在构造器完成时点；逸出期间读到的必为默认值）\nafter join (hb established): final=42 plain=42\nracy publication: final=42 (JLS 17.5 保证，断言) plain=42 (无保证，观察值)\nPASS final freeze: escape/default and racy-publication branches asserted\n\n== 4. progress: CAS retry cost and dispersed counting ==\nAtomicInteger CAS loop total=400000 casFailures=338821（重试为观察值：无个体时延上界）\nLongAdder total=400000（增量分散到 Cell；sum() 非原子快照，仅在无并发更新时精确）\nPASS progress: totals asserted exact; retry counts recorded as observation\n\n== 5. ABA: node identity reuse corrupts a lock-free stack ==\nplain stack: stale CAS(top=a -> saved next=b) succeeded=true\nplain stack after stale CAS: [B]（A 丢失、已移除的 B 复活——引用回到旧值但状态已变）\nstamped stack: stale CAS with stamp 0 succeeded=false（版本 0->3，旧版本拒绝）\nstamped stack intact: top=A next=null stamp=3\nPASS ABA: plain reference resurrected removed node; stamped CAS rejected\n\n== 6. weakCompareAndSetPlain retry loop and lazySet release ==\nweakCompareAndSetPlain loop total=20000（允许偶发失败，重试循环仍收敛）\nlazySet(1) -> volatile get(): payload observed=42（release 写与 acquire 读配对，断言通过）\nPASS weak CAS / lazySet: retry loop exact; release-acquire asserted\n\n== 7. ConcurrentHashMap write-side failure branches ==\ncomputeIfAbsent mapping mutates same map -> IllegalStateException（映射函数不得在计算中修改本映射）\ncomputeIfAbsent mapping throws -> propagated, mapping absent=true\ncompute on existing key throws -> old value kept=true\nmerge remapping returns null -> removed=true returned=null\nput(null, v) -> NullPointerException\nput(k, null) -> NullPointerException\nPASS CHM failures: recursive/exception/merge-null/null-key branches\n\n== 8. computeIfAbsent progress: same key serialized, other key free ==\nput(same key A) waited ~606ms（与锁内映射函数串行：单键原子性的进度代价）\nput(other key B) waited ~0ms（不同桶，不受该桶锁影响）\nPASS computeIfAbsent progress: same-key serialized >=450ms, other-key <350ms\n\n== 9. CopyOnWriteArrayList write side: copy on every write ==\narray identity changes on add=true on set=true（每次写都全量复制底层数组）\niterator created before add sees 3 elements; list now has 4\nsnapshot iterator.remove() -> UnsupportedOperationException\naddIfAbsent(fresh) first=true duplicate=false size=5\ntwo writers x1000 concurrent adds -> size=2005（写写在锁上互斥；读无锁）\nPASS COW write side: copy identity, snapshot, UOE, addIfAbsent, writers\n\n== 10. ConcurrentLinkedQueue write side ==\noffer/poll FIFO order=[0, 1, 2, 3, 4]\nempty: peek=null poll=null element() -> NoSuchElementException\noffer(null) -> NullPointerException\nsize() on 300000 elements=300000 took 3013µs（遍历计数 O(n)；非并发下准确，并发更新中只是估计）\niterator created then head polled: iterator still returns head=true（弱一致观察值，非契约）\nPASS CLQ write side: FIFO, empty branches, null rejection, size cost\n\nALL U07 SECTIONS PASS\n",
   "stderrNote": "JAVA_TOOL_OPTIONS 回显与 TypeProbe unchecked 诊断，见 environment.stderrNote",
   "tmpLeft": 0
  },
  {
   "name": "unknown-mode",
   "command": [
    "bash",
    "labs/java-senior/run.sh",
    "nonsense"
   ],
   "exit": 2,
   "stdout": "",
   "note": "未知模式退出 2（用法串含 jmm）"
  },
  {
   "name": "extra-arg",
   "command": [
    "bash",
    "labs/java-senior/run.sh",
    "jmm",
    "extra"
   ],
   "exit": 2,
   "note": "参数过多退出 2"
  },
  {
   "name": "bad-java-home",
   "command": [
    "bash",
    "labs/java-senior/run.sh",
    "jmm"
   ],
   "env": {
    "JAVA_HOME": "/bad/home"
   },
   "exit": 2,
   "note": "无效 JAVA_HOME 退出 2"
  },
  {
   "name": "jdk21-rejected",
   "command": [
    "bash",
    "labs/java-senior/run.sh",
    "jmm"
   ],
   "env": {
    "JAVA_HOME": "/Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home"
   },
   "exit": 2,
   "note": "版本守卫拒绝 JDK21（java version 21.0.5），本入口固定 JDK17"
  },
  {
   "name": "concurrency-recheck",
   "command": [
    "bash",
    "labs/concurrency/run.sh"
   ],
   "env": {
    "JAVA_HOME": "/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home"
   },
   "timeoutSeconds": 60,
   "exit": 0,
   "note": "U07 用本机 Oracle JDK 17.0.12 复跑旧 ConcurrencyProbe（历史 README 记录的 Liberica 17.0.19 不在本机）：六节输出与 labs/concurrency/README 登记值一致（plain/volatile final=1、CAS final=2、ABA cas=true/false、CHM 懒初始化 sizeCtl 0→12→24、CHM(1000)→2048/1536、merge 80000、null 双拒绝）。原 out/concurrency-probe.txt 历史产物不改写。",
   "tmpLeft": 0
  }
 ]
}