X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fnet%2Fsf%2Fopenrocket%2Fgui%2Fmain%2FExceptionHandler.java;h=4099f019120d4c4942c5db5c1b795854ea96d29d;hb=f8aca85893990faf46d59ab89e9861f46c66dff3;hp=93474b1c6b17262e96b0ac43fefcf9203570ed06;hpb=0d0afe488300aca47d09ac7651f8185190afb21f;p=debian%2Fopenrocket diff --git a/src/net/sf/openrocket/gui/main/ExceptionHandler.java b/src/net/sf/openrocket/gui/main/ExceptionHandler.java index 93474b1c..4099f019 100644 --- a/src/net/sf/openrocket/gui/main/ExceptionHandler.java +++ b/src/net/sf/openrocket/gui/main/ExceptionHandler.java @@ -12,8 +12,10 @@ public class ExceptionHandler implements Thread.UncaughtExceptionHandler { /** * A memory reserve of 0.5 MB of memory, that can be freed when showing the dialog. + *

+ * This field is package-private so that the JRE cannot optimize its use away. */ - private static volatile byte[] memoryReserve = null; + static volatile byte[] memoryReserve = null; private static ExceptionHandler instance = null; @@ -27,16 +29,17 @@ public class ExceptionHandler implements Thread.UncaughtExceptionHandler { public void uncaughtException(final Thread t, final Throwable e) { // Free memory reserve if out of memory - if (e instanceof OutOfMemoryError) { + if (isOutOfMemoryError(e)) { memoryReserve = null; handling = false; } + e.printStackTrace(); + try { if (handling) { - System.err.println("Exception is currently being handled, " + - "dumping exception instead:"); + System.err.println("Exception is currently being handled, ignoring:"); e.printStackTrace(); return; } @@ -70,6 +73,63 @@ public class ExceptionHandler implements Thread.UncaughtExceptionHandler { } + /** + * Handle an error condition programmatically without throwing an exception. + * This can be used in cases where recovery of the error is desirable. + * + * @param message the error message. + */ + public static void handleErrorCondition(String message) { + handleErrorCondition(new InternalException(message)); + } + + + /** + * Handle an error condition programmatically without throwing an exception. + * This can be used in cases where recovery of the error is desirable. + * + * @param message the error message. + * @param exception the exception that occurred. + */ + public static void handleErrorCondition(String message, Exception exception) { + handleErrorCondition(new InternalException(message, exception)); + } + + + /** + * Handle an error condition programmatically without throwing an exception. + * This can be used in cases where recovery of the error is desirable. + * + * @param exception the exception that occurred. + */ + public static void handleErrorCondition(final Exception exception) { + final ExceptionHandler handler = instance; + + try { + + if (handler == null) { + // Not initialized, simply print the exception + exception.printStackTrace(); + return; + } + + final Thread thread = Thread.currentThread(); + + if (SwingUtilities.isEventDispatchThread()) { + handler.showDialog(thread, exception); + } else { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + handler.showDialog(thread, exception); + } + }); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** * The actual handling routine. * @@ -79,22 +139,28 @@ public class ExceptionHandler implements Thread.UncaughtExceptionHandler { private void showDialog(Thread t, Throwable e) { // Out of memory - if (e instanceof OutOfMemoryError) { + if (isOutOfMemoryError(e)) { JOptionPane.showMessageDialog(null, new Object[] { - "Out of memory!", - "You should immediately close unnecessary design windows,
" + + "OpenRocket can out of available memory!", + "You should immediately close unnecessary design windows,", "save any unsaved designs and restart OpenRocket!" }, "Out of memory", JOptionPane.ERROR_MESSAGE); return; } + // Create the message + String msg = e.getClass().getSimpleName() + ": " + e.getMessage(); + if (msg.length() > 90) { + msg = msg.substring(0, 80) + "..."; + } + // Unknown Error if (!(e instanceof Exception)) { JOptionPane.showMessageDialog(null, new Object[] { "An unknown Java error occurred:", - e.getMessage(), + msg, "You should immediately close unnecessary design windows,
" + "save any unsaved designs and restart OpenRocket!" }, "Unknown Java error", JOptionPane.ERROR_MESSAGE); @@ -102,11 +168,12 @@ public class ExceptionHandler implements Thread.UncaughtExceptionHandler { } - // Normal exception, show question dialog - + // Normal exception, show question dialog int selection = JOptionPane.showOptionDialog(null, new Object[] { "OpenRocket encountered an uncaught exception. This typically signifies " + - "a bug in the software.", " ", + "a bug in the software.", + "        " + msg + "", + " ", "Please take a moment to report this bug to the developers.", "This can be done automatically if you have an Internet connection." }, "Uncaught exception", JOptionPane.DEFAULT_OPTION, @@ -145,6 +212,9 @@ public class ExceptionHandler implements Thread.UncaughtExceptionHandler { } + /** + * Reserve the buffer memory that is freed in case an OutOfMemoryError occurs. + */ private static void reserveMemory() { memoryReserve = new byte[MEMORY_RESERVE]; for (int i=0; i + * This method is required because Apple's JRE implementation sometimes + * masks OutOfMemoryErrors within RuntimeExceptions. Idiots. + * + * @param t the throwable to examine. + * @return whether this is an out-of-memory condition. + */ + private boolean isOutOfMemoryError(Throwable t) { + while (t != null) { + if (t instanceof OutOfMemoryError) + return true; + t = t.getCause(); + } + return false; + } + + + /** * Handler used in modal dialogs by Sun Java implementation. */ public static class AwtHandler { public void handle(Throwable t) { + + /* + * Detect and ignore bug 6828938 in Sun JRE 1.6.0_14 - 1.6.0_16. + */ + if (t instanceof ArrayIndexOutOfBoundsException) { + final String buggyClass = "sun.font.FontDesignMetrics"; + StackTraceElement[] elements = t.getStackTrace(); + if (elements.length >= 3 && + (buggyClass.equals(elements[0].getClassName()) || + buggyClass.equals(elements[1].getClassName()) || + buggyClass.equals(elements[2].getClassName()))) { + System.err.println("Ignoring Sun JRE bug 6828938: " + t); + return; + } + } + + if (instance != null) { instance.uncaughtException(Thread.currentThread(), t); } } } + + + private static class InternalException extends Exception { + public InternalException() { + super(); + } + + public InternalException(String message, Throwable cause) { + super(message, cause); + } + + public InternalException(String message) { + super(message); + } + + public InternalException(Throwable cause) { + super(cause); + } + } }