
CRaC 不支持在恢复时通过命令行向已暂停的进程重新注入 main(String[] args) 参数;恢复本质是状态续跑,而非重启。需改用运行时可变的数据源(如文件、环境变量或系统属性)配合 afterRestore() 回调实现参数传递。
crac 不支持在恢复时通过命令行向已暂停的进程重新注入 `main(string[] args)` 参数;恢复本质是状态续跑,而非重启。需改用运行时可变的数据源(如文件、环境变量或系统属性)配合 `afterrestore()` 回调实现参数传递。
CRaC(Coordinated Restore at Checkpoint)的设计哲学是应用状态的精确冻结与还原,而非传统意义上的“启动+参数注入”。当你执行 java -XX:CRaCRestoreFrom=cr 时,JVM 并非重新调用 main() 方法,而是将内存、线程、堆栈、打开的文件描述符等整个运行时上下文原样恢复——此时 main 方法早已执行完毕,args 数组早已脱离作用域,因此无法被覆盖或重传。
✅ 正确做法:利用 Resource 接口的生命周期回调,在恢复后主动读取外部参数。以下是推荐实现方案:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
-
定义可恢复资源类(实现 Resource 接口):
import jdk.crac.*;
public class ArgsProvider implements Resource { private static String[] runtimeArgs;
@Override
public void beforeCheckpoint(Context extends Resource> context) throws Exception {
// 可选:保存当前运行时状态(如清理临时资源)
}
@Override
public void afterRestore(Context extends Resource> context) throws Exception {
// ✅ 关键:恢复后读取新参数
String argsFile = System.getProperty("crac.args.file");
if (argsFile != null && !argsFile.trim().isEmpty()) {
runtimeArgs = Files.readString(Paths.get(argsFile))
.trim()
.split("\s+");
} else {
// 回退到环境变量
String envArgs = System.getenv("CRAC_RUNTIME_ARGS");
runtimeArgs = (envArgs != null) ? envArgs.split("\s+") : new String[0];
}
System.out.println("✅ Restored with args: " + Arrays.toString(runtimeArgs));
}
public static String[] getRuntimeArgs() {
return runtimeArgs != null ? runtimeArgs : new String[0];
}
}
2. **注册资源并初始化**(在 `main` 中尽早注册):
```java
public class Main {
public static void main(String[] args) throws Exception {
// 注册恢复感知资源
Core.getGlobalContext().register(new ArgsProvider());
// 启动逻辑(含 checkpoint 触发)
if (args.length > 0 && "--checkpoint".equals(args[0])) {
Core.checkpoint();
return;
}
// 正常业务逻辑中使用动态参数
String[] dynamicArgs = ArgsProvider.getRuntimeArgs();
System.out.println("Business logic receives: " + Arrays.toString(dynamicArgs));
}
}
-
恢复时传参操作流程:
# 1. 创建参数文件(每次恢复前可更新) echo "arg1 arg2 --verbose" > /tmp/crac-args.txt
2. 恢复并指定参数源
$JAVA_CMD -Dcrac.args.file=/tmp/crac-args.txt -XX:CRaCRestoreFrom=cr
⚠️ 注意事项: - ❌ 不要尝试修改 `main` 的原始 `args` —— 它在恢复时不可访问且无意义; - ✅ 所有恢复后逻辑必须放在 `afterRestore()` 中,确保在 JVM 状态完全就绪后执行; - ? 若参数含敏感信息,优先使用受权限保护的本地文件或 JVM 系统属性(避免环境变量泄露); - ? 建议配合 `Core.checkpoint()` 显式触发检查点,并在 `beforeCheckpoint()` 中做轻量预处理(如刷新缓冲区),提升一致性。 总结:CRaC 的参数传递不是“重启式注入”,而是“恢复后拉取”。将参数解耦为外部可变状态,再通过标准化回调接入业务逻辑,既符合 CRaC 的设计约束,也保持了应用架构的清晰性与可测试性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










