使用getRuntimeMXBean().getStartTime()获取服务实际启动时间的疑问
核心结论
ManagementFactory.getRuntimeMXBean().getStartTime() 不会返回2022/01/01 10:00:00这个旧JVM的启动时间,在你日志里的jvm 2进程中调用该方法,返回的一定是新JVM实例的启动时间2022/01/01 10:58:09。
原理说明
ManagementFactory.getRuntimeMXBean().getStartTime()的返回值绑定的是当前调用方法所在的JVM进程实例的初始化时间,本质是记录当前Java进程从操作系统层面启动完成的时间点,和外层托管JVM的wrapper服务生命周期完全独立:
- 你日志里标记的
jvm 1和jvm 2是两个完全独立、生命周期不重叠的操作系统进程,旧JVM退出后内存数据会被完全回收,新JVM不会继承旧进程的任何运行时状态。 - 不管是JVM主动触发重启、还是异常崩溃后被wrapper拉起,只要是新启动的JVM进程,调用该方法拿到的都是新进程自己的启动时间,和之前运行过的JVM没有任何关系。
不同业务场景的获取方案
- 如果你的业务逻辑依赖的是当前JVM进程的启动时间(比如计算当前进程连续运行时长、进程内指标统计):直接使用
ManagementFactory.getRuntimeMXBean().getStartTime()即可,返回值准确可靠,不需要额外处理。 - 如果你的业务逻辑依赖的是外层wrapper服务的初始启动时间(也就是不管中间JVM重启多少次,要拿到最开始手动启动服务的2022/01/01 10:00:00这个时间点):不要通过JVM内置的RuntimeMXBean获取,推荐两种可靠方案:
- 方案1:利用Java Service Wrapper自带的环境变量
WRAPPER_START_TIME,该变量记录的是wrapper进程自身的启动时间,内部JVM重启不会修改这个值,JVM启动后直接读取环境变量即可拿到。 - 方案2:wrapper服务首次启动拉起第一个JVM时,将初始启动时间持久化到本地配置文件、注册表等固定存储位置,后续JVM重启后直接从该存储位置读取初始值即可,注意不要依赖JVM关闭时的回调传值,JVM崩溃、强杀场景下回调逻辑不会执行,会导致数据丢失。
- 方案1:利用Java Service Wrapper自带的环境变量
内容的提问来源于stack exchange,提问作者Bhuvanesh Waran
相关产品推荐
相关产品推荐

