{
 "date": "2026-10-25",
 "timezone": "Asia/Shanghai",
 "issue": 48,
 "batch": "U11",
 "sourceTag": "OpenJDK jdk-17.0.12+7 (fixed mechanism source)",
 "environment": {
  "os": "macOS 26.7.1 (25G241, 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–U10 相同的本机 Oracle JDK 17.0.12+8（x86_64）。绿跑 all 开始于 2026-10-24T20:59:12Z（北京时间 2026-10-25 04:59:12），结束 20:59:44Z，exit=0。",
  "runPolicy": "每次运行由包装命令设置 90 秒（all 150 秒）perl alarm 上限；diagnose.sh 显式 JVM 参数全部如实登记——gclog: -Xms64m -Xmx64m -XX:+UseG1GC -Xlog:gc:file=...:uptime,tags；fullgc explicit: -Xms32m -Xmx32m；fullgc allocfail: -Xms16m -Xmx16m；fullgc humongous: -Xms32m -Xmx32m -XX:G1HeapRegionSize=1m；observe child: -Xms128m -Xmx128m -Xlog:gc,safepoint；tlab: -Xms32m -Xmx32m -Xlog:gc+tlab=debug。唯一 mktemp 根目录（build+evidence）EXIT/INT/TERM trap 定向删除并传给 java.io.tmpdir；子进程 observe-child 自限 25 秒，脚本只 attach 自己启动的 PID。",
  "stderrNote": "无预期外 stderr；-Xlog 输出全部写入自身临时目录文件（探针用 -Du11.gclog 回读），不在仓库留运行产物。"
 },
 "tdd": {
  "redGreen": [
   "红1（G1 分配失败升级路径只做一次 Full GC 的误解）：断言 16m 堆 1MiB 数组保留到 OOM 的日志里 G1 Compaction Pause 恰好 1 条（/tmp/u11-red/Red1.java），实跑 exit=1，输出『RED1 unexpected: expected exactly 1 G1 Compaction Pause, saw 2』——satisfy_failed_allocation 升级梯是 普通 Full GC → 最大压缩 Full GC 两级；绿探针第 2b 节断言 compaction>=2 落位。",
   "红2（诊断命令不改变被观察者的误解）：断言 jcmd GC.class_histogram 后 jstat FGC 不变（/tmp/u11-red/red2.sh），实跑 exit=1，输出『RED2 unexpected: class_histogram changed jstat FGC from 0 to 1』——默认直方图请求 Full GC（cause: Heap Inspection Initiated GC）；绿入口 observe 模式把 FGC 差量上升作为断言而非假设。",
   "红3（每次 GC 后 used 一定严格下降的误解）：断言 allocfail 全部 Pause 行 after < before（/tmp/u11-red/Red3.java），实跑 exit=1，列出 6 条 after == before 的行（7M->7M、13M->13M 等）——高存活/全保留负载下 GC 无法释放内存是正常行为不是日志错误；绿探针第 1 节断言放宽为 after<=before<=capacity 的字段不变量。",
   "红4（1MiB 数组在小堆上不是 Humongous 分配的误解）：断言 16m 堆 1MiB 数组日志无 '(G1 Humongous Allocation)' 原因（/tmp/u11-red/Red4.java），实跑 exit=1——该堆 region=1MiB，1MiB 数组加头部大于半 region，直接走 Humongous；绿探针第 2b/2c 节按原因标签在场断言落位。"
  ],
  "compileFixes": "开发期修复如实记录不计红绿：(1) gclog 模式首版在无负载时直接回读日志，断言『无 Pause Young』失败（exit 1），补上 2 秒有界 churn 负载后转绿——该失败是脚本缺陷不是误解断言，未计入红绿；(2) Pause 行正则首版用 [^)]* 解析原因括号，'(System.gc())' 与 '(G1 Evacuation Pause)'（含数字 G1）导致字段错位/漏配，改为行尾锚定的 before->after(capacity) ms 字段匹配。",
  "noFakeRed": "四个红均为先按常见误解写下的真实预期（一次 Full GC 就放弃、诊断只读不改、GC 必然释放内存、小堆大数组不是 Humongous）被 JDK17 实测推翻，随后按固定 tag 源码/工具语义修正转绿，不倒造 red。"
 },
 "runs": [
  {
   "name": "all-final",
   "command": ["bash", "labs/gc/diagnose.sh", "all"],
   "env": {"JAVA_HOME": "/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home"},
   "startedUtc": "2026-10-24T20:59:12+00:00",
   "timeoutSeconds": 150,
   "timedOut": false,
   "exit": 0,
   "stdout": "== 1. GC log anatomy ==\nobserved (not a contract): arrays=183836\nok: Pause Young x1663, Remark x0, Cleanup x0, Full x0\nok: all 1663 pause lines parse as before->after(capacity) ms with after<=before<=capacity\nok: concurrent-cycle dedup: start-marker lines=0, completed (with duration)=0\nobserved (not a contract): pauses=1663 mean=0.164ms max=1.047ms\nobserved (not a contract): first=GC(0) Pause Young (Normal) (G1 Evacuation Pause) 23M->1M(64M) 1.040ms\nobserved (not a contract): last =GC(1662) Pause Young (Normal) (G1 Evacuation Pause) 39M->1M(64M) 0.155ms\nPASS section 1 / ALL U11 GCLOG PASS\n== 2a explicit ==\nok: explicit gc produced 'Pause Full (System.gc())' x1\nobserved (not a contract): [0.038s][gc] GC(0) Pause Full (System.gc()) 1M->1M(32M) 1.489ms\nPASS section 2a / ALL U11 FULLGC-EXPLICIT PASS\n== 2b allocfail ==\nok: controlled OOM is 'Java heap space' after retaining ~6 MiB\nok: escalation ladder reached 'Pause Full (G1 Compaction Pause)' x2 after young/marking lines (first young at line 1, first full at line 9)\nobserved ladder: GC(0) Pause Young (Concurrent Start) (G1 Humongous Allocation) 7M->7M(16M) 0.767ms → GC(1) Concurrent Mark Cycle → Pause Remark 11M->11M(16M) → Pause Cleanup → Concurrent Mark Cycle 1.861ms → GC(2) Pause Young (Concurrent Start) (G1 Humongous Allocation) 13M->13M(16M) → GC(4) Pause Young (Normal) (G1 Humongous Allocation) → GC(5) Pause Full (G1 Compaction Pause) 13M->13M(16M) 1.119ms → GC(6) Pause Full (G1 Compaction Pause) 13M->13M(16M) 0.837ms → GC(3) Concurrent Mark Cycle 2.670ms\nPASS section 2b / ALL U11 FULLGC-ALLOCFAIL PASS\n== 2c humongous ==\nok: controlled OOM is 'Java heap space' after retaining 5 x 4MiB arrays\nok: '(G1 Humongous Allocation)' cause tag on 4 lines; Pause Full x2\nobserved: GC(0/2/4) Pause Young (Concurrent Start) (G1 Humongous Allocation) 11M/16M/26M ->same(32M)；GC(7/8) Pause Full (G1 Compaction Pause) 26M->26M(32M) 1.121/0.707ms\nPASS section 2c / ALL U11 FULLGC-HUMONGOUS PASS\n== observe (child pid=98138, -Xms128m -Xmx128m) ==\njstat -gcutil 500ms x2: S0 0.00, S1 25.00, E 12.66, O 2.41, M 72.51, CCS 17.44, YGC 1422→1649, YGCT 0.330→0.383, FGC 0, FGCT 0.000, CGC 0, GCT 0.330→0.383\nGC.heap_info: garbage-first heap total 131072K used 1706K; region size 1024K, 2 young (2048K), 1 survivors (1024K); Metaspace used 371K committed 512K\nobserved (not a contract): jstat FGC before class_histogram=0 after=1\nok: GC.class_histogram observably raised jstat FGC (0 -> 1)\nok: child log shows the induced full gc: [4.544s][gc] GC(1952) Pause Full (Heap Inspection Initiated GC) 2M->1M(128M) 2.141ms\nok: Thread.print itself ran at a safepoint: [4.901s][safepoint] Safepoint \"PrintThreads\", Time since last: 578957 ns, Reaching safepoint: 94915 ns, At safepoint: 286761 ns, Total: 381676 ns\nok: JFR recording carries jdk.GarbageCollection(name=G1New, cause=G1 Evacuation Pause)\nobserved (not a contract): tenuringThreshold = 15\nPASS observe\n== 3 tlab ==\nok: parsed 2715 'TLAB totals' lines\nobserved (not a contract): GC(0) TLAB totals: thrds: 2  refills: 2 max: 1 slow allocs: 41 max 41 waste: 76.7% gc: 450680B max: 293584B slow: 0B max: 0B\nobserved (not a contract): GC(1) TLAB totals: thrds: 1  refills: 1 max: 1 slow allocs: 52 max 52 waste: 50.0% gc: 262128B max: 262128B slow: 0B max: 0B\nobserved (not a contract): maxWastePercent=76.7 arrays=217000\nPASS section 3 / ALL U11 TLAB PASS",
   "tmpLeft": 0,
   "stabilityNote": "终轮前后各模式独立直跑 exit=0（gclog/fullgc/observe/tlab 各至少一次）；Pause 计数、mean/max、waste%、arrays 数为按轮观察值不断言精确值；FGC 0→1 的观察者效应在两轮 observe 中均复现。"
  },
  {
   "name": "legacy-runsh-regression-sandbox",
   "command": "cp labs/gc/{GcReachabilityProbe,TriColorSatbSim,AllocationPressure}.java labs/gc/run.sh 到 /tmp 沙盒副本后 JAVA_HOME=jdk17 ./run.sh",
   "exit": 0,
   "stdout": "runtime: java version \"17.0.12\" ...；三实验正常结束，末行 retained=12000；产物 reachability-probe.txt/gc.log/tricolor-satb.txt/allocation-pressure.txt/g1-marking.log 全部生成",
   "note": "在沙盒副本复跑以免改写仓库登记资产 asset-28–32；仓库 labs/gc/out 经 git status 确认未变。历史断言（weakOnly=false、三色两分支、3 个并发标记周期量级）原样通过，不改写。"
  },
  {
   "name": "unknown-mode",
   "command": ["bash", "labs/gc/diagnose.sh", "nonsense"],
   "exit": 2,
   "stdout": "Usage: diagnose.sh [all|gclog|fullgc|observe|tlab]",
   "note": "未知模式退出 2"
  },
  {
   "name": "extra-arg",
   "command": ["bash", "labs/gc/diagnose.sh", "gclog", "extra"],
   "exit": 2,
   "stdout": "Usage: diagnose.sh [all|gclog|fullgc|observe|tlab]",
   "note": "参数过多退出 2"
  },
  {
   "name": "jdk21-rejected",
   "command": ["bash", "labs/gc/diagnose.sh", "gclog"],
   "env": {"JAVA_HOME": "/Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home"},
   "exit": 2,
   "note": "版本守卫拒绝 JDK21（java version 21.0.5），本入口固定 JDK17"
  },
  {
   "name": "no-java-home-fallback-graalvm17",
   "command": ["bash", "labs/gc/diagnose.sh", "gclog"],
   "env": {"JAVA_HOME": ""},
   "exit": 0,
   "note": "与 jvm-senior/run.sh 相同的回退边界：/usr/libexec/java_home -v 17 解析到 GraalVM 17.0.12，版本守卫按『17.』放行且 gclog 探针在该构建亦全绿 exit=0。如实记录：未显式 JAVA_HOME 时运行构建可能是 GraalVM 17 而非登记的 Oracle 17.0.12+8，文档化入口仍要求显式 JAVA_HOME；这是回退解析的边界观察不是负例。"
  }
 ],
 "honesty": {
  "notAContract": "GC 次数、停顿均值/最大值、FGC/FGCT、waste%、TLAB 统计字节、OOM 前保留量、GraalVM 回退运行均为单机观察值；16m/32m 小堆是为受控触发失败分支的人工配置，不代表生产堆形态；全部分配失败与 OOM 都是探针自身进程内的受控失败，OOM 被捕获后进程 exit=0。",
  "unreproducedScenarios": "Metadata GC Threshold 与 Heap Dump Initiated GC 原因未在探针中注入触发（前者需类加载压力、后者属 heap dump 高影响操作，按 gcCause.cpp 词表与页 E 既有 HeapDumpDCmd 源码推导登记）；ZGC/Parallel 收集器侧的日志行未采集（本票运行环境为默认 G1，Parallel 摘录按固定 tag 源码推导、标注未在本机运行）；跨多轮生产的 Full GC 频率/容量结论不做任何外推。"
 }
}
