package ecologylab.appframework; import java.util.ArrayList; import ecologylab.collections.Scope; import ecologylab.generic.ConsoleUtils; import ecologylab.generic.Debug; import ecologylab.generic.ExceptionHandler; /** * Handle running out of memory. Basically, inform the user, ask if they wish * to save, then exit combinformation. * */ public class OutOfMemoryErrorHandler extends Debug { private static ArrayList<ExceptionHandler> handlers = new ArrayList<ExceptionHandler>(); private static Scope objectRegistry; private static boolean previouslyRanOut = false; /** * The OutOfMemoryError memory threshold (in bytes) that means we should shut down */ private static final long OUT_OF_MEMORY_THRESHOLD = 4000000; private OutOfMemoryErrorHandler() {} public static void registerObjectRegistry(Scope oRegistry) { objectRegistry = oRegistry; } /** * Register an ExceptionHandler for callback when an exception * is thrown * @param exceptionHandler The ExceptionHandler to add. */ public static void registerHandler(ExceptionHandler exceptionHandler) { handlers.add(exceptionHandler); } /** * Call to register that an exception has ocurred. Results in all * registered handlers being notified. * @param e */ public static void handleException(OutOfMemoryError e) { //in case we get here prematurely if (Memory.getFreeMemoryInBytes() > OUT_OF_MEMORY_THRESHOLD) { ConsoleUtils.obtrusiveConsoleOutput("OutOfMemoryErrorHandler BYPASSED PREMATURE MEMORY ERROR"); e.printStackTrace(); return; } //ConsoleUtils.obtrusiveConsoleOutput("Free Memory: " + currentFreeMemory + " bytes"); //ConsoleUtils.obtrusiveConsoleOutput("Memory Threshold: " + OUT_OF_MEMORY_THRESHOLD + " bytes"); //don't bother synchronizing because we're probably hosed and can't do it. if (previouslyRanOut) //we already handled it return; previouslyRanOut = true; Debug.println("Calling OUT OF MEMORY Handlers cause: "); e.printStackTrace(); for (int i=0; i<handlers.size(); i++) { handlers.get(i).handleException(new Exception(e.getMessage()), objectRegistry); } } }