【问题标题】:How do I extract a timestamp from the heap dump如何从堆转储中提取时间戳
【发布时间】:2019-11-28 17:09:20
【问题描述】:

很遗憾,我忘记记录进行堆转储的时间。我希望在堆中的某个地方,标准库缓存类似System.currentTimeMillis() 的东西。不幸的是,我没有任何缓存它的业务对象。

一个困难的选择是浏览所有线程,并查看它们的局部变量是否在某处存储了时间戳。但是,这不是我可以应用于所有堆转储的技术。

我查看了 openJDK 中的 java.lang.System,它看起来不像我们缓存了一个值。我们使用本机代码获取当前时间,但我们不会将本机代码的结果存储在任何地方。 https://hg.openjdk.java.net/jdk8/jdk8/jdk/file/4d891c8db5c1/src/share/classes/java/lang/System.java

【问题讨论】:

  • 我没有堆转储了,但我认为它是 gzip,然后上传,然后我下载,然后我对其进行压缩。我不确定创建日期是否仍然可用。

标签: heap-dump hprof


【解决方案1】:

堆转储文件在其标题中包含一个时间戳。但是开头有一个以零结尾的字符串,如果字符串不总是相同的话,这将使时间戳的确切位置动态化。

因此,为了在您的实际文件中进行简短的临时查找,您可以简单地假设通常的位置并将时间戳提取为

try(RandomAccessFile raf = new RandomAccessFile(hprofFileLocation, "r")) {
    raf.seek(23);
    System.out.println(hprofFileLocation+" created "+Instant.ofEpochMilli(raf.readLong()));
}

而一个干净的解决方案将读取以零结尾的字符串,跳过后续的 int 值并从结果位置读取时间戳,例如

try(FileChannel fch = FileChannel.open(
                          Paths.get(hprofFileLocation), StandardOpenOption.READ)) {
    ByteBuffer bb = fch.map(
        FileChannel.MapMode.READ_ONLY, 0, Math.min(Integer.MAX_VALUE, fch.size()));
    do {} while(bb.get() != 0); // zero terminate string, usually "JAVA PROFILE 1.0.[12]"
    int pointerSize = bb.getInt();
    long timeStamp = bb.getLong();
    System.out.println(hprofFileLocation+" created "+Instant.ofEpochMilli(timeStamp));
}

【讨论】:

    猜你喜欢
    • 2015-01-10
    • 2016-08-10
    • 1970-01-01
    • 2013-07-02
    • 2020-07-07
    • 2019-06-10
    • 2020-04-27
    • 2017-03-09
    • 2017-09-16
    相关资源
    最近更新 更多