All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.jy2.di.internal.ExitProcessOnUncaughtException Maven / Gradle / Ivy

There is a newer version: 0.0.39
Show newest version
package com.github.jy2.di.internal;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.State;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.github.jy2.di.JyroscopeDi;
import com.github.jy2.di.LogSeldom;

public class ExitProcessOnUncaughtException implements UncaughtExceptionHandler {

	public static final LogSeldom LOG = JyroscopeDi.getLog();

	public static final int LOG_PUBLISH_TIME = 2000;

	public static String logFolder = "/tmp";
	public static String memberName = "unknown";

//	private static com.sun.management.ThreadMXBean mxBean = (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean();	

	static public void register() {
		Thread.setDefaultUncaughtExceptionHandler(new ExitProcessOnUncaughtException());
	}
	
	private ExitProcessOnUncaughtException() {
	}

	@Override
	public void uncaughtException(Thread t, Throwable e) {
		// avoid getting into infinite loop if it gets another out of memory error
		Thread.setDefaultUncaughtExceptionHandler(null);
		try {
			saveCrashLog(t, e);
			LOG.fatal("Uncaught exception caught in thread " + t, e);
			LOG.fatal("All Stack Traces:\n" + getAllStackTraces() + "\n" + "Heap:\n" + getHeapInfo());
			// give logging system time to publish the logs
			unconditionalSleep(LOG_PUBLISH_TIME);
		} finally {
			Runtime.getRuntime().halt(1);
		}
	}

	private void saveCrashLog(Thread t, Throwable e) {
		String stamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
		String fileName = logFolder + "/crash-" + memberName.replace('/', '_') + "-" + stamp + ".txt";

		// get stack trace
		StringWriter stringWriter = new StringWriter();
		PrintWriter printWriter = new PrintWriter(stringWriter);
		e.printStackTrace(printWriter);

		String content = "Uncaught exception caught in thread " + t + "\n" + stringWriter + "\nAll Stack Traces:\n"
				+ getAllStackTraces() + "\n" + "Heap:\n" + getHeapInfo();

		File f = new File(fileName);
		if (f.getParentFile() != null) {
			f.getParentFile().mkdirs();
		}

		try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
			writer.write(content);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}

	private void unconditionalSleep(int howLong) {
		long start = System.currentTimeMillis();
		while (true) {
			long time = System.currentTimeMillis();
			long dt = howLong - (time - start);
			if (dt <= 0) {
				break;
			}
			try {
				Thread.sleep(dt);
			} catch (InterruptedException e) {
			}
		}
	}

	public static String getAllStackTraces() {
		String ret = "";
		Map allStackTraces = Thread.getAllStackTraces();

		for (Entry entry : allStackTraces.entrySet()) {
			State state = entry.getKey().getState();
			if (state == State.WAITING || state == State.TIMED_WAITING) {
				continue;
			}
			ret += getThreadInfo(entry.getKey(), entry.getValue()) + "\n";
		}
		return ret;
	}

	public static String getHeapInfo() {
		String ret = "";
		List memBeans = ManagementFactory.getMemoryPoolMXBeans();
		for (MemoryPoolMXBean mpool : memBeans) {
			MemoryUsage usage = mpool.getUsage();

			String name = mpool.getName();
			long used = usage.getUsed();
			long max = usage.getMax();
			int pctUsed = (int) (used * 100 / max);
			ret += " " + name + " total: " + (max / 1024) + "K, used: " + (used / 1024) + "K, " + pctUsed + "% used\n";
		}
		return ret;
	}

	public static String getThreadInfo(Thread thread, StackTraceElement[] stack) {
		String ret = "";
		ret += "\n\"" + thread.getName() + "\"";
		if (thread.isDaemon())
			ret += " daemon";
		ret += " prio=" + thread.getPriority() + " tid=" + String.format("0x%08x", thread.getId());
		if (stack.length > 0)
			ret += " in " + stack[0].getClassName() + "." + stack[0].getMethodName() + "()";
//		ret += "\n   allocated bytes: " + mxBean.getThreadAllocatedBytes(thread.getId());
		ret += "\n   java.lang.Thread.state: " + thread.getState() + "\n";
		ret += getStackTrace(stack);
		return ret;
	}

	public static String getStackTrace(StackTraceElement[] stack) {
		String ret = "";
		for (StackTraceElement element : stack)
			ret += "\tat " + element + "\n";
		return ret;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy