开发者

how to generate thread dump java on out of memory error

  • does java 6 generate thread dump in addition to heap dump (java_pid14941.hprof)

  • this is what happened to one of my applications.

    java.lang.OutOfMemoryError: GC overhead limit exceeded Dumping heap to java_pid14941.hprof ...

  • I开发者_运维技巧 did find ava_pid14941.hprof in working directory, but didn't find any file which contains thread dump. I need to know what all the threads were doing when I got this OutOfMemory error.

  • Is there any configuration option which will generate thread dump in addition to heap dump on out of memory exception?


If you're in a Linux/Unix environment you can do this:

-XX:OnOutOfMemoryError="kill -3 %p"

This way you don't have to have your application generate periodic thread dumps and you'll get a snapshot when it actually chokes.

With %p, you don't need to pass the PID, JVM will automatically pick the correct process id as mentioned here.


How to generate thread dump java on out of memory error?

Your question can be simplified into:

  • how to generate a thread dump

and:

  • how to catch an out of memory error (don't pay attention to naysayer here, they're missing the bigger picture, see my comment)

So it's actually quite easy, you could do it like this:

  • install a default uncaught exception handler

  • upon catching an uncaught exception, check if you have an OutOfMemoryError

  • if you have an OutOfMemoryError, generate yourself a full thread dump and either ask the user to send it to you by email or offer to send it automatically

Bonus: it works fine on 1.5 too :)

 Thread.setDefaultUncaughtExceptionHandler( new Thread.UncaughtExceptionHandler() {
     public void uncaughtException( final Thread t, final Throwable e ) {
         ...
     }

You may want to look into this:

 e.getMessage();

and this:

Thread.getAllStackTraces();

I'm doing this all the time in an app that is shipped on hundreds of different 1.5 and 1.6 JVM (on different OSes).


It's possible to trigger a thread dump when OnOutOfMemoryError is triggered using jstack. e.g:-

jstack -F pid > /var/tmp/<identifier>.dump


Based on the accepted answer I created utility class. This one you can define as a Spring bean and you're all set with extended logging.

import java.util.Iterator;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class UncaughtExceptionLogger {

    private final static Logger logger = LoggerFactory.getLogger(UncaughtExceptionLogger.class);

    @PostConstruct
    private void init() {
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            public void uncaughtException(final Thread t, final Throwable e) {
                String msg = ExceptionUtils.getRootCauseMessage(e);
                logger.error(String.format("Uncaght exception handler captured expcetion '%s'", msg), e);
                if (msg.contains("unable to create new native thread")) {
                    String dump = captureThreadDump();
                    logger.error(String.format(
                            "OutOfMemoryError has been captured for threads limit. Thread dump: \n %s", dump), e);
                }
                if (ExceptionUtils.getRootCause(e) instanceof OutOfMemoryError) {
                    String dump = captureThreadDump();
                    logger.error(String.format("OutOfMemoryError has been captured. Thread dump: \n %s", dump), e);
                }
            }
        });
    }

    public static String captureThreadDump() {
        /**
         * http://stackoverflow.com/questions/2787976/how-to-generate-thread-
         * dump-java-on-out-of-memory-error
         * http://henryranch.net/software/capturing-a-thread-dump-in-java/
         */
        Map<Thread, StackTraceElement[]> allThreads = Thread.getAllStackTraces();
        Iterator<Thread> iterator = allThreads.keySet().iterator();
        StringBuffer stringBuffer = new StringBuffer();
        while (iterator.hasNext()) {
            Thread key = (Thread) iterator.next();
            StackTraceElement[] trace = (StackTraceElement[]) allThreads.get(key);
            stringBuffer.append(key + "\r\n");
            for (int i = 0; i < trace.length; i++) {
                stringBuffer.append(" " + trace[i] + "\r\n");
            }
            stringBuffer.append("");
        }
        return stringBuffer.toString();
    }
}


-XX:OnOutOfMemoryError="kill -3 %p"

The JVM argument to take thread dump sadly don't work. Child process cannot end SIGQUIT to parent.

Oracle has -XX:CrashOnOutOfMemoryError but this is available on Java 8.


I don't think there is anything in java that would provide you with on-exit thread dumps. I tackle this when necessary by having a cronjob that does periodic kill -3 pid. Yes, it does clutter the logs a bit, but the footprint is still negligible.

And if you are suffering from OOM, it might be be beneficial to see how the situation evolved thread-wise.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜