joseph
joseph

Reputation: 2835

How do I extract a timestamp from the heap dump

Unfortunately, I forgot to record the time that I took the heap dump. I hope that somewhere in the heap, the standard library caches something like System.currentTimeMillis(). Unfortunately, I do not have any business objects that cache it.

One difficult option I have it to browse all the threads, and see if their local variables stored a timestamp somewhere. However, this is not technique I can apply to all heap dumps.

I looked at java.lang.System in openJDK and it doesn't look like we cache a value. We go to native code to get the current time, but we don't store the result from native code anywhere. https://hg.openjdk.java.net/jdk8/jdk8/jdk/file/4d891c8db5c1/src/share/classes/java/lang/System.java

Upvotes: 4

Views: 2226

Answers (2)

Aaron Meriwether
Aaron Meriwether

Reputation: 111

Here is how I do it from the command-line using Perl:

perl -e '1 while ord getc; read STDIN, $_, 12; print scalar gmtime 0.001 * unpack "x4Q>"' <heapdump.hprof

It does the same as @holger's Java code, but no need to compile anything. The output is in GMT, but if you use localtime instead of gmtime you will get output in whatever your local timezone is.

Upvotes: 1

Holger
Holger

Reputation: 298539

The heap dump file contains a timestamp right in its header. But there is a zero-terminated string at the beginning, which would make the exact position of the timestamp dynamic, if the string wouldn’t be always the same.

So for a short, ad-hoc lookup in your actual files, you might simply assume the usual position and extract the timestamp as

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

whereas a clean solution would read the zero terminated string, skip the subsequent int value and read the timestamp from the resulting position, e.g.

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

Upvotes: 5

Related Questions