{
 "date": "2026-10-25",
 "timezone": "Asia/Shanghai",
 "issue": 47,
 "batch": "U10",
 "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–U09 相同的本机 Oracle JDK 17.0.12+8（x86_64）。绿跑开始于 2026-10-24T20:1xZ（北京时间 2026-10-25 04:1x）。",
  "runPolicy": "每次运行由包装命令设置 90 秒（classjit-tiers/all 120–180 秒）perl alarm 上限；run.sh 显式 JVM 参数 -Xms64m -Xmx512m（classjit 另加 -Xlog:class+init=info；classjit-tiers 四配置分别 -Xint / -XX:TieredStopAtLevel=1 / 默认 / -XX:-DoEscapeAnalysis）并如实记录；唯一 TMPDIR 传入并作为 java.io.tmpdir；run.sh 自身 mktemp 唯一编译目录 + EXIT/INT/TERM trap 清理；探针进程内 JFR 录制（jdk.Deoptimization/jdk.Compilation 事件）dump 到 java.io.tmpdir 并在 finally 删除。",
  "stderrNote": "无预期外 stderr；-Xlog:class+init=info 的 [info][class,init] 行按设计混入 classjit stdout（真实开关输出即证据）；编译期错误两次如实记录见 tdd.compileFixes。"
 },
 "tdd": {
  "redGreen": [
   "红1（子类名读取静态字段会初始化子类的误解，2026-10-24T20:0xZ 前后）：按常见误解断言 Sub.PARENT_FIELD 读取后 Sub 已初始化（/tmp/u10-red/Red1.java），实跑 exit=1，输出『RED1 unexpected: Sub was NOT initialized (misconception said it would be)』——JLS 12.4.1 只初始化声明类 Parent；修正方向后绿探针第 1 节按『Parent 初始化而 Sub 不初始化、随后触碰 Sub 自有静态才初始化 Sub』两断言落位。",
   "红2（读取 static final 常量一定触发初始化的误解，2026-10-24T20:0xZ 前后）：断言读取 ConstHolder.K 后声明类已初始化（Red2.java），实跑 exit=1，输出『RED2 unexpected: ConstHolder was NOT initialized』——常量变量被 javac 内联为 ConstantValue，读取不触发 <clinit>；修正后绿探针以『常量 K 不初始化、static final Integer BOXED 非常量变量读取即初始化』对照断言落位。",
   "红3（JIT 编译后不会再去优化的误解，2026-10-24T20:0xZ 前后）：单形态预热 Add 后调用第二实现 Mul，断言 0 个 jdk.Deoptimization 事件（Red3.java），实跑 exit=1，输出『RED3 unexpected: 6 deoptimization events observed after compiled warmup』——类型画像失效触发 predicate/profile_predicate uncommon trap；修正后绿探针第 4 节断言 ourDeopts>=1 且 ourCompilations>=1，事件明细按观察值打印。",
   "红4（每次 new 都有真实堆分配的误解，2026-10-24T20:0xZ 前后）：断言不逃逸 pair 循环 100 万次分配字节 >= 16MiB（Red4.java，与 U09 相同预热法 2 万次调用进入 C2），实跑 exit=1，输出『RED4 unexpected: non-escaping loop allocated almost nothing (allocatedBytes=0)』——C2 标量替换消除了全部 pair 分配；修正后绿探针第 3 节断言 noEscapeBytes*8 < escapeBytes 且 noEscapeBytes < 8MiB，与逃逸循环 46,583,352 字节同 JVM 对照。"
  ],
  "compileFixes": "开发期修复如实记录不计红绿：(1) BrokenInit 首版在 static 块末尾直接 throw，javac 拒绝编译（初始化程序必须能够正常完成），改为 JvmSeniorLab.Broken 同型的『static int trigger = fail()』写法；(2) 反射读 LazyLoadClass.nonConstant 首版用 getField（只查 public），NoSuchFieldException 后改 getDeclaredField（同包可访问）。",
  "noFakeRed": "四个红均为先按常见误解写下的真实预期（子类名触发子类初始化、final 常量触发初始化、编译后不去优化、new 必分配）被 JDK17 实测推翻，随后按 JLS/HotSpot 契约修正转绿，不倒造 red。"
 },
 "runs": [
  {
   "name": "classjit-final",
   "command": [
    "bash",
    "labs/jvm-senior/run.sh",
    "classjit"
   ],
   "env": {
    "JAVA_HOME": "/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home"
   },
   "startedUtc": "2026-10-24T20:18:00+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. class initialization triggers (loading vs initializing) ==\nok: forName(initialize=false) returns the class but does NOT run <clinit>\nok: forName(initialize=true) runs <clinit> exactly once\nok: a second forName(initialize=true) does not run <clinit> again\nok: ClassLoader.loadClass loads but does NOT initialize\nok: reflective getstatic on a non-constant field triggers initialization\nok: reading a constant variable is inlined and does NOT initialize the declaring class\nok: static final Integer is NOT a constant variable: reading it DOES initialize\nok: creating Parent[] does not initialize Parent\nok: Sub.PARENT_FIELD initializes the declaring class Parent, not Sub\nok: touching Sub's own static initializes Sub (superclass already done)\nok: failed <clinit> leaves the erroneous state: first EIIE then NCDFE, no retry\nPASS section 1\n\n== 2. same-thread reentrant initialization reads the zero value ==\nok: reentrant readY() during <clinit> observes y's default 0, so x=0 and y=7\nPASS section 2\n\n== 3. scalar replacement observed via getCurrentThreadAllocatedBytes ==\nok: pairLoop checksum equals the closed form n*n\nok: both loops compute the same closed-form checksum\nok: non-escaping loop allocates far less than the escaping loop (scalar replacement)\nobserved (not a contract): noEscapeBytes=0 escapeBytes=46583352\nPASS section 3\n\n== 4. observable deoptimization: monomorphic warmup then a second type ==\nobserved deopt (not a contract): run reason=predicate action=maybe_recompile\nobserved deopt (not a contract): run reason=profile_predicate action=maybe_recompile\nobserved deopt (not a contract): run reason=profile_predicate action=maybe_recompile\nobserved deopt (not a contract): run reason=profile_predicate action=maybe_recompile\nobserved deopt (not a contract): run reason=profile_predicate action=maybe_recompile\nok: add/mul checksums match the independent long-arithmetic oracle\nok: the profile-invalidation call really deoptimized our compiled code (>=1 event)\nok: our methods were actually JIT compiled in this recording (>=1 event)\nobserved (not a contract): addMs=0 mulFirstMs=11 mulSecondMs=4 ourDeopts=5 ourCompilations=18\nPASS section 4\n\n== 5. CompilationMXBean and code cache observation ==\nok: compilation bean reports a non-negative total compile time\nobserved (not a contract): jit=HotSpot 64-Bit Tiered Compilers totalCompilationTimeMs=1132 (code cache detail needs jcmd Compiler.codecache / -Xlog:codecache=info, both external)\nPASS section 5\nALL U10 SECTIONS PASS\ndone sections",
   "classInitLogNote": "同一 stdout 含 -Xlog:class+init=info 真实开关输出，例如『[0.081s][info][class,init] 589 Initializing 'ClassJitProbe$LazyForName' (0x...)』恰出现在 forName(initialize=true) 断言处、而 forName(initialize=false) 段无该行——日志与断言互证；完整行见正文实验章。",
   "tmpLeft": 0,
   "stabilityNote": "终轮前后同入口独立直跑连续 3 轮 exit=0 全绿（/tmp 独立目录，已清理）；计时/字节/事件数按轮打印不断言精确值；ourDeopts 在 5–6 间波动，reason 组成略有差异，按观察值记录。"
  },
  {
   "name": "classjit-tiers-final",
   "command": [
    "bash",
    "labs/jvm-senior/run.sh",
    "classjit-tiers"
   ],
   "env": {
    "JAVA_HOME": "/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home"
   },
   "timeoutSeconds": 120,
   "timedOut": false,
   "exit": 0,
   "stdout": "== tier config: -Xint (interpreter only) ==\ntierObservation pairLoop: ms=581 allocatedBytes=64000000\ntierObservation escapeLoop: ms=334 allocatedBytes=22480096\ntierObservation arithmeticLoop: ms=225\n== tier config: -XX:TieredStopAtLevel=1 (C1 only) ==\ntierObservation pairLoop: ms=30 allocatedBytes=64000000\ntierObservation escapeLoop: ms=10 allocatedBytes=22480096\ntierObservation arithmeticLoop: ms=38\n== tier config: default (tiered through C2) ==\ntierObservation pairLoop: ms=0 allocatedBytes=0\ntierObservation escapeLoop: ms=14 allocatedBytes=22480064\ntierObservation arithmeticLoop: ms=20\n== tier config: -XX:-DoEscapeAnalysis ==\ntierObservation pairLoop: ms=31 allocatedBytes=64000000\ntierObservation escapeLoop: ms=13 allocatedBytes=22480096\ntierObservation arithmeticLoop: ms=19\n（每个配置均先打印 ok: pairLoop/escapeLoop/arithmeticLoop checksum 三断言再打印观察行）",
   "note": "四种配置的三个校验和全部等于闭式/oracle 值——解释执行与 C1/C2 编译执行结果一致是本对照的确定性结论；耗时与分配字节是单机单轮观察值非契约。观察：C1（TieredStopAtLevel=1）不做逃逸分析（64,000,000 字节照常分配），默认 C2 标量替换把 pairLoop 分配降为 0，-XX:-DoEscapeAnalysis 后 C2 也恢复 64,000,000 字节分配。",
   "tmpLeft": 0
  },
  {
   "name": "regression-jvm-senior-lab",
   "command": "JVM_LAB_JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home bash labs/jvm-senior/build.sh && java -cp BUILD JvmSeniorLab init | loader(-Xlog:class+load=info,class+unload=info) | layout(-javaagent:size-agent.jar) | escape(-Xms64m -Xmx64m -Xlog:gc)",
   "exit": 0,
   "stdout": "init: attempt=1 ExceptionInInitializerError / attempt=2 NoClassDefFoundError\nloader: sameClass=false parentInstance=false tcclHeld=true afterRelease=false + [info][class,unload] unloading class JvmSeniorLab$Payload\nlayout: Object=16 Sample=32 Object[3]=32 byte[3]=24\nescape: checksum=400000000000000（本轮默认 EA 运行无 Pause Young 行）",
   "note": "U10 前序探针四模式按原文档命令原样复跑通过，历史断言不改写；作为账本『已讲清』点的本轮登记证据。"
  },
  {
   "name": "all-final",
   "command": [
    "bash",
    "labs/jvm-senior/run.sh",
    "all"
   ],
   "env": {
    "JAVA_HOME": "/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home"
   },
   "timeoutSeconds": 180,
   "timedOut": false,
   "exit": 0,
   "stdoutNote": "classjit（ALL U10 SECTIONS PASS 在列）+ classjit-tiers 四配置全部正常结束，37 处 PASS/ok 输出；终轮 deopt 观察行 addMs=0 mulFirstMs=9 mulSecondMs=4 ourDeopts=6 ourCompilations=17（与前轮 5/18 不同，观察值波动如实呈现）",
   "tmpLeft": 0
  },
  {
   "name": "unknown-mode",
   "command": [
    "bash",
    "labs/jvm-senior/run.sh",
    "nonsense"
   ],
   "exit": 2,
   "stdout": "Usage: run.sh [all|classjit|classjit-tiers]",
   "note": "未知模式退出 2"
  },
  {
   "name": "extra-arg",
   "command": [
    "bash",
    "labs/jvm-senior/run.sh",
    "classjit",
    "extra"
   ],
   "exit": 2,
   "stdout": "Usage: run.sh [all|classjit|classjit-tiers]",
   "note": "参数过多退出 2"
  },
  {
   "name": "jdk21-rejected",
   "command": [
    "bash",
    "labs/jvm-senior/run.sh",
    "classjit"
   ],
   "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/jvm-senior/run.sh",
    "classjit"
   ],
   "env": {
    "JAVA_HOME": ""
   },
   "exit": 0,
   "note": "与 java-senior（回退解析到 21 被拒）不同：本机 /usr/libexec/java_home -v 17 解析到 /Users/gaochao/Library/Java/JavaVirtualMachines/graalvm-jdk-17.0.12，版本守卫按『17.』放行且该构建上探针亦全绿 exit=0。如实记录：未显式 JAVA_HOME 时运行构建可能是 GraalVM 17 而非登记的 Oracle 17.0.12+8，文档化入口仍要求显式 JAVA_HOME；这不是负例，是回退解析的边界观察。"
  }
 ],
 "honesty": {
  "notAContract": "计时（ms）、分配字节、deopt 事件数与 reason 组成、totalCompilationTimeMs、GraalVM 回退运行均为单机观察值；跨配置对比不外推生产性能。",
  "unreproducedScenarios": "类层次分析（CHA）失效导致的批量 nmethod 失效与 OSR 栈上替换细节未在本探针驱动复现，正文按固定 tag 源码机制推导并标注；-Xlog:compilation* 的 made not entrant 行未进断言（日志文案随版本变化）。"
 }
}
