heap-dumphprof

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


Solution

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