17

How can i create a heap dump from within my application, without using the class HotSpotDiagnosticMXBean. Due to access restriction of java/rt.jar i am not able to compile it with a dependency to HotSpotDiagnosticMXBean. I know how solve the eclipse.compiler error, but how can i fix it for my build? Is there an alternative to way to create a heap dump programmatically?

Community
  • 1
  • 1
Chriss
  • 5,157
  • 7
  • 41
  • 75
  • did you read this: http://java.sun.com/developer/technicalArticles/J2SE/monitoring/ ? – Dmitry Zagorulkin Sep 06 '12 at 08:28
  • 1
    Can you not lift the access restriction so you can do it the way you are supposed to? Either you need to do this and you can have access or you don't in which case you shouldn't try. – Peter Lawrey Sep 06 '12 at 08:28
  • @Peter Lawrey i can't lift the restriction (maybe there is a compiler option?) the second option is to trigger a heap dump in a other way. – Chriss Sep 06 '12 at 08:40

5 Answers5

23

Okay,seems like you can bypass the restriction by using reflection :

package lab.heapdump;

import javax.management.MBeanServer;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;


@SuppressWarnings("restriction")
public class HeapDump {
    // This is the name of the HotSpot Diagnostic MBean
    private static final String HOTSPOT_BEAN_NAME =
         "com.sun.management:type=HotSpotDiagnostic";

    // field to store the hotspot diagnostic MBean 
    private static volatile Object hotspotMBean;

    /**
     * Call this method from your application whenever you 
     * want to dump the heap snapshot into a file.
     *
     * @param fileName name of the heap dump file
     * @param live flag that tells whether to dump
     *             only the live objects
     */
    static void dumpHeap(String fileName, boolean live) {
        // initialize hotspot diagnostic MBean
        initHotspotMBean();
        try {
            Class clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean");
            Method m = clazz.getMethod("dumpHeap", String.class, boolean.class);
            m.invoke( hotspotMBean , fileName, live);
        } catch (RuntimeException re) {
            throw re;
        } catch (Exception exp) {
            throw new RuntimeException(exp);
        }
    }

    // initialize the hotspot diagnostic MBean field
    private static void initHotspotMBean() {
        if (hotspotMBean == null) {
            synchronized (HeapDump.class) {
                if (hotspotMBean == null) {
                    hotspotMBean = getHotspotMBean();
                }
            }
        }
    }

    // get the hotspot diagnostic MBean from the
    // platform MBean server
    private static Object getHotspotMBean() {
        try {
            Class clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean");
            MBeanServer server = ManagementFactory.getPlatformMBeanServer();
            Object bean = 
                ManagementFactory.newPlatformMXBeanProxy(server,
                HOTSPOT_BEAN_NAME, clazz);
            return bean;
        } catch (RuntimeException re) {
            throw re;
        } catch (Exception exp) {
            throw new RuntimeException(exp);
        }
    }

    public static void main(String[] args) {
        // default heap dump file name
        String fileName = "D:\\heap.bin";
        // by default dump only the live objects
        boolean live = true;

        // simple command line options
        switch (args.length) {
            case 2:
                live = args[1].equals("true");
            case 1:
                fileName = args[0];
        }

        // dump the heap
        dumpHeap(fileName, live);
    }
}
Doug
  • 382
  • 1
  • 4
  • Reflection works! One have only to check if the `HotSpotDiagnosticMXBean` class is available in the current jdk. – Chriss Sep 06 '12 at 10:41
  • 2
    Appears to have been adapted from https://blogs.oracle.com/sundararajan/entry/programmatically_dumping_heap_from_java – Thorbjørn Ravn Andersen Sep 02 '16 at 14:49
  • Are you sure this will work? If I write this: getMethod("dumpHeap", String.class, boolean.class) .. I get error "not applicable for arguments String, Class, Class" ... so I have to use array: new Class[] {String.class, boolean.class} as the 2nd parameter and invoking is done like this: m.invoke( hotspotMBean , new Object[] {fileName, Boolean.valueOf(live)}); – Racky Nov 15 '16 at 09:08
5
package ru.test;

import com.sun.management.HotSpotDiagnosticMXBean;
import org.junit.Test;

import java.io.IOException;
import java.lang.management.ManagementFactory;

public class TestDump {
    @Test
    public void test() throws IOException {
        long i = 6789;
        String s = "HELLO";
        System.out.println(i);
        System.out.println(s);

        HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy(ManagementFactory.getPlatformMBeanServer(),
                "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
        mxBean.dumpHeap("C:\\temp\\dump\\heap1.bin", true);
    }
}

Out:

6789
HELLO    


Process finished with exit code 0
Zedong
  • 71
  • 1
  • 5
0

You can copy the rt.jar which has the HotSpotDiagnosticMXBean.class to a different location. Refer the copied jar in build path using "Add External jar". This allows you to create Object and get the Heap dump.

new HotSpotDiagnostic().dumpHeap("d:\\HeapDump1",true);

I was able to generate Heapdump this way. I was looking for any runtime conflict of jars error. Luckily none.

Kumar
  • 182
  • 13
-1

VisualVM can make a heap dump.

You can also try the jhat command on linux systems.

Doug
  • 382
  • 1
  • 4
  • 2
    I know, but i want to trigger a heapdump from within my application, without the need of a external programm. – Chriss Sep 06 '12 at 08:34
-1

This class is public, so the only reason you might not have access to it is you don't have it in your version of the JVM as its too old.

The example linked to compiles and runs fine in Java 6 and 7. If possibly, try upgrading to a recent version of Java.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 2
    I'am using java7. The Problem is that HotSpotDiagnosticMXBean is not a public HotSpotDiagnosticMXBean class (it is not part of the jdk). This class exists only in the oracle java distribution, it is JVM dependent. – Chriss Sep 06 '12 at 09:37
  • 1
    This means the feature is JVM dependent and you can compile the code, but it might not run on JVMs which don't support this feature. Which flavours of JVMs are you using? – Peter Lawrey Sep 06 '12 at 09:39