logging and unit test updates
[debian/openrocket] / src / net / sf / openrocket / gui / main / ExceptionHandler.java
index c1529a3c122d34665e4137928a831409708827d0..4099f019120d4c4942c5db5c1b795854ea96d29d 100644 (file)
@@ -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.
+        * <p>
+        * 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,7 +29,7 @@ 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;
                }
@@ -101,14 +103,14 @@ public class ExceptionHandler implements Thread.UncaughtExceptionHandler {
         * @param exception             the exception that occurred.
         */
        public static void handleErrorCondition(final Exception exception) {
-               final ExceptionHandler handler;
+               final ExceptionHandler handler = instance;
 
                try {
 
-                       if (instance == null) {
-                               handler = new ExceptionHandler();
-                       } else {
-                               handler = instance;
+                       if (handler == null) {
+                               // Not initialized, simply print the exception
+                               exception.printStackTrace();
+                               return;
                        }
 
                        final Thread thread = Thread.currentThread();
@@ -137,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!",
-                                               "<html>You should immediately close unnecessary design windows,<br>" +
+                                               "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,
                                                "<html>You should immediately close unnecessary design windows,<br>" +
                                                "save any unsaved designs and restart OpenRocket!"
                                        }, "Unknown Java error", JOptionPane.ERROR_MESSAGE);
@@ -160,13 +168,7 @@ public class ExceptionHandler implements Thread.UncaughtExceptionHandler {
                }
                
                
-               // Normal exception, show question dialog
-               String msg = e.getClass().getSimpleName() + ": " + e.getMessage();
-               if (msg.length() > 90) {
-                       msg = msg.substring(0, 80) + "...";
-               }
-               
-               
+               // 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.", 
@@ -210,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<MEMORY_RESERVE; i++) {
@@ -218,6 +223,29 @@ public class ExceptionHandler implements Thread.UncaughtExceptionHandler {
        }
 
        
+       
+       /**
+        * Return whether this throwable was caused by an OutOfMemoryError
+        * condition.  An exception is deemed to be caused by OutOfMemoryError
+        * if the throwable or any of its causes is of the type OutOfMemoryError.
+        * <p>
+        * 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.
         */