heap-dump - 如何从堆转储中提取时间戳

标签 heap-dump hprof

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

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

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

最佳答案

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

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

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));
}

关于heap-dump - 如何从堆转储中提取时间戳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57116971/

相关文章:

java - 如何分析具有常见泄漏嫌疑的heapdump

java - 添加并命名书签 jprofiler

android - HPROF 后我的应用程序中有巨大的 byte[]

android - 如何为使用 Proguard 构建/从 Google Play 安装的应用程序生成 HPROF 内存转储

android - MAT (Eclipse Memory Analyzer) - 如何从内存转储中查看位图

java - 从二进制堆转储中提取 JVM 正常运行时间

java - 如何生成仅包含 JRE 的堆转储?

java - 具有以固定速率运行的可运行对象的 Java 项目可以在一段时间后停止吗?我的在大约 40 小时后仍然卡住

java - tomcat 在内存不足错误时不生成 hprof 文件

5亿(双)值的Java数据结构?