JVM 17 运行时与故障实验
使用 JDK 17(历史运行基线为 Oracle JDK 17.0.12,macOS x86_64;当前机器用 JVM_LAB_JAVA_HOME 指定实际安装路径),从仓库根执行:
export JVM_LAB_JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home
JVM_LAB_BUILD=$(bash labs/jvm-senior/build.sh)
"$JVM_LAB_JAVA_HOME/bin/java" -javaagent:"$JVM_LAB_BUILD/size-agent.jar" -cp "$JVM_LAB_BUILD" JvmSeniorLab layout
"$JVM_LAB_JAVA_HOME/bin/java" -cp "$JVM_LAB_BUILD" JvmSeniorLab init
"$JVM_LAB_JAVA_HOME/bin/java" -cp "$JVM_LAB_BUILD" JvmSeniorLab loader
bash labs/jvm-senior/collect.sh "$JVM_LAB_BUILD" cpubuild.sh在临时目录编译SizeAgent和JvmSeniorLab。layout通过Instrumentation获得浅大小,不测深对象图;init比较首次初始化失败和后续访问;loader比较同名字节码由不同加载器定义后的类型身份。collect.sh仅启动自己的有界子进程,采集线程、堆、NMT和JFR,生成证据目录后打印路径。可选择cpu、heap、direct、blocked、deadlock、churn,实验限于合成进程,不能对任意用户服务注入故障。
NMT只覆盖HotSpot所跟踪的本地内存分类,不等于完整RSS;JFR及jcmd依赖attach权限。Linux线程与cgroup证据须在Linux环境补采,本机macOS结果不能证明容器节流。压缩指针、对齐和GC参数影响对象大小;源码推导与运行输出必须各自注明版本。
NMT 两时序受控复验
nmt_compare.py 是独立公开入口,不改变旧 collect 模式。固定 JDK17 HotSpot,Python3标准库编排,在临时目录编译 NmtBaselineProbe.java;不需要第三方包。macOS可用 $(/usr/libexec/java_home -v 17);Linux显式指定已安装的JDK17路径。
python3 labs/jvm-senior/nmt_compare.py --java-home "$JVM_LAB_JAVA_HOME" --output /tmp/nmt-new-run
python3 labs/jvm-senior/nmt_compare.py --java-home "$JVM_LAB_JAVA_HOME" --tracking off --output /tmp/nmt-off-new-runoutput必须尚不存在,避免覆盖历史结果。正常入口退出0;off入口的baseline必然无法启动追踪,应退出1且保存诊断,不能当成意外失败或假通过。阶段握手控制 A分配→baseline→diff / B baseline→分配→diff;两次都只保留12MiB并通过BufferPool交叉观测。子进程30s上限,堆96MiB与direct32MiB上限;失败只清理自身子进程。jcmd必须能同用户attach,失败/超时会保留已有证据并非零退出。
本次真实环境与输出见两时序原始证据、off预期失败证据。它们记录Liberica17.0.19+11-LTS、Darwin27.0.0 arm64、Python3.9.6,与Oracle17.0.12历史实验分开。Other分类验证限本组HotSpot实现;NMT、BufferPool都不是RSS。其他构建不满足分类/噪声容差时保留失败,不推广为所有版本契约。完整教学、时序表、来源和逐题评分见诊断工具正文。
U10 类初始化触发边界与 JIT 观察
run.sh 是 U10 新增的统一公开入口(白名单 all|classjit|classjit-tiers;未知模式、参数过多、JDK 工具缺失和非 JDK17 退出 2;macOS 未设 JAVA_HOME 时经 java_home 发现 17,本机会解析到 GraalVM 17.0.12——文档化入口仍要求显式 JAVA_HOME 指向登记的 Oracle 17.0.12)。入口以唯一临时目录编译 ClassJitProbe.java,EXIT/INT/TERM trap 定向删除;探针进程内 JFR 录制只 dump 到自身 java.io.tmpdir 并在 finally 删除。每次运行 JVM 参数固定为 -Xms64m -Xmx512m,classjit 另加 -Xlog:class+init=info,classjit-tiers 四配置分别 -Xint / -XX:TieredStopAtLevel=1 / 默认 / -XX:-DoEscapeAnalysis,全部如实登记。
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home
bash labs/jvm-senior/run.sh classjit
bash labs/jvm-senior/run.sh classjit-tiersclassjit 对应类加载正文、内存区域正文与JIT 正文:forName(initialize=false)/loadClass 加载不初始化、常量变量内联不触发而 static final Integer 触发、Parent[] 与 Sub.PARENT_FIELD 声明类规则、EIIE→NCDFE 错误状态不重试、同线程重入读零值、同 JVM 分配字节对照(不逃逸循环 0 字节 vs 逃逸循环 46,583,352 字节)、单形态预热后第二实现触发 uncommon trap(进程内订阅 JFR jdk.Deoptimization,实测 5–6 条 predicate/profile_predicate 事件,观察值非契约)、CompilationMXBean 累计编译耗时观察。classjit-tiers 用四个独立 JVM 跑同一负载,只断言各配置校验和,跨配置耗时与分配字节是观察值:本机单轮 pairLoop 在 -Xint/C1-only/默认/关EA 下分别为 581ms/30ms/0ms/31ms 与 64,000,000/64,000,000/0/64,000,000 字节——C1 不做逃逸分析、默认 C2 标量替换消除全部分配、单独关 EA 恢复分配,这是台阶归属的证据不是倍数承诺。U10 运行版本为 Oracle JDK 17.0.12+8(x86_64);完整命令、退出状态、四次真实红绿与负例记录见实测证据。