| public class SimpleDump { public static void main(String args[]) { System.out.println(args[0]); } } |
| Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0 at SimpleDump.main(SimpleDump.java:3) |
| public class WindowDump { public static void main(String args[]) throws Exception { ThreadGroup group = new LoggingThreadGroup("Logger"); new Thread(group, "myThread") { public void run() { System.out.println(1 / 0); } }.start(); } } |
| import java.util.logging.*; public class LoggingThreadGroup extends ThreadGroup { private static Logger logger; public LoggingThreadGroup(String name) { super(name); } public void uncaughtException(Thread t, Throwable e) { // Initialize logger once if (logger == null) { logger = Logger.getLogger("example"); Handler handler = LoggingWindowHandler.getInstance(); logger.addHandler(handler); } logger.log(Level.WARNING, t.getName(), e); } } |
| import java.util.logging.*; public class LoggingWindowHandler extends Handler { private static LoggingWindow window; private static LoggingWindowHandler handler; private LoggingWindowHandler() { configure(); window = new LoggingWindow("Logging window...", 400, 200); } public static synchronized LoggingWindowHandler getInstance() { if (handler == null) { handler = new LoggingWindowHandler(); } return handler; } /** * Get any configuration properties set */ private void configure() { LogManager manager = LogManager.getLogManager(); String className = getClass().getName(); String level = manager.getProperty(className + ".level"); setLevel((level == null) ? Level.INFO : Level.parse(level)); String filter = manager.getProperty(className + ".filter"); setFilter(makeFilter(filter)); String formatter = manager.getProperty(className + ".formatter"); setFormatter(makeFormatter(formatter)); } private Filter makeFilter(String name) { Filter f = null; try { Class c = Class.forName(name); f = (Filter)c.newInstance(); } catch (Exception e) { if (name != null) { System.err.println("Unable to load filter: " + name); } } return f; } private Formatter makeFormatter(String name) { Formatter f = null; try { Class c = Class.forName(name); f = (Formatter)c.newInstance(); } catch (Exception e) { f = new SimpleFormatter(); } return f; } // Overridden abstract Handler methods public void close() { } public void flush() { } /** * If record is loggable, format it and add it to window */ public void publish(LogRecord record) { String message = null; if (isLoggable(record)) { try { message = getFormatter().format(record); } catch (Exception e) { reportError(null, e, ErrorManager.FORMAT_FAILURE); return; } try { window.addLogInfo(message); } catch (Exception e) { reportError(null, e, ErrorManager.WRITE_FAILURE); } } } } |
| import java.awt.*; import javax.swing.*; public class LoggingWindow extends JFrame { private JTextArea textArea; public LoggingWindow(String title, final int width, final int height) { super(title); EventQueue.invokeLater(new Runnable() { public void run() { setSize(width, height); textArea = new JTextArea(); JScrollPane pane = new JScrollPane(textArea); textArea.setEditable(false); getContentPane().add(pane); setVisible(true); } }); } public void addLogInfo(final String data) { EventQueue.invokeLater(new Runnable() { public void run() { textArea.append(data); } }); } } |
![]() 图 1. 记录的堆栈跟踪 |
| public interface Thread.UncaughtExceptionHandler { public void uncaughtException(Thread, Throwable); } |
| getUncaughtExceptionHandler() 和 setUncaughtExceptionHandler() 。 getDefaultUncaughtExceptionHandler() 和 setDefaultUncaughtExceptionHandler() 。 |
| public class HandlerDump { public static void main(String args[]) throws Exception { Thread.UncaughtExceptionHandler handler = new LoggingThreadGroup("Logger"); Thread.currentThread().setUncaughtExceptionHandler(handler); System.out.println(1 / 0); } } |