Sigar Java API在Solaris Sparc系统中获取进程启动时间显示为未来时间
问题分析与解决
在Solaris Sparc环境下,Sigar Java API获取进程启动时间返回未来时间,而Perl命令结果正确,大概率是以下几个原因导致:
1. 时间基准或单位不匹配
Sigar的ProcTime.getStartTime()在部分Solaris Sparc的实现中,错误返回了系统启动以来的时间(而非从epoch时间1970-01-01开始的标准时间戳),或者返回的是微秒/纳秒级数值却被当成毫秒处理。而Perl通过stat /proc/[pid]获取的是进程启动的epoch秒级时间戳,两者基准完全不同,自然会得到未来时间。
验证方法:直接打印Sigar返回的startTime原始长整型值,和Perl命令输出的时间戳对比:
- 先修正你原Perl命令的语法错误,正确获取并打印时间戳:
# 打印进程启动时间的原始epoch秒数 perl -e 'print ((stat(shift))[9], "\n")' /proc/34411 # 格式化输出时间 perl -e '@d=localtime((stat(shift))[9]); printf "%4d%02d%02d%02d%02d%02d\n", $d[5]+1900, $d[4]+1, $d[3], $d[2], $d[1], $d[0]' /proc/34411 - 如果Sigar返回的
startTime远小于Perl的epoch秒数(比如只有几百万),说明它是系统启动后的毫秒数,此时需要结合系统启动的epoch时间计算真实启动时间:try { // 获取系统运行的秒数 long uptimeSeconds = sigar.getUptime().getUptime(); // 计算系统启动的epoch毫秒数 long systemBootTime = System.currentTimeMillis() - (uptimeSeconds * 1000); // 获取Sigar返回的进程启动后耗时(毫秒) long startTimeAfterBoot = sigar.getProcTime(pid).getStartTime(); // 真实进程启动时间 = 系统启动时间 + 启动后耗时 long actualStartTime = systemBootTime + startTimeAfterBoot; } catch (SigarException e) { e.printStackTrace(); }
2. 字节序处理错误
Solaris Sparc是大端(Big-Endian)字节序,若Sigar的本地底层代码读取进程启动时间时,未正确处理字节序,会将时间戳解析为错误的数值,最终转换为未来时间。这种情况需要查看Sigar针对Solaris Sparc的实现源码,确认psinfo结构体中pr_start字段的读取逻辑是否正确。
3. Sigar版本兼容性问题
旧版本的Sigar对Solaris Sparc的进程信息获取存在bug,建议升级到最新稳定版的Sigar,或者临时改用Java调用系统命令的方式获取启动时间:
String pid = "34411"; try { Process process = Runtime.getRuntime().exec(new String[]{"ps", "-efo", "lstart", pid}); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = reader.readLine()) != null) { if (line.contains(pid)) { // 解析输出行中的启动时间字符串 System.out.println("进程启动时间:" + line.split("\\s+", 8)[7]); break; } } reader.close(); process.waitFor(); } catch (IOException | InterruptedException e) { e.printStackTrace(); }
内容的提问来源于stack exchange,提问作者user_vs
相关产品推荐
相关产品推荐

