package net.i2p.router.tasks; import java.io.File; import java.util.concurrent.atomic.AtomicBoolean; import net.i2p.router.Router; import net.i2p.router.RouterContext; import net.i2p.router.util.EventLog; import net.i2p.util.I2PThread; import net.i2p.util.Log; import net.i2p.util.SystemVersion; /** * Kaboom * * @since 0.8.12 moved from Router.java */ public class OOMListener implements I2PThread.OOMEventListener { private final RouterContext _context; private final AtomicBoolean _wasCalled = new AtomicBoolean(); public OOMListener(RouterContext ctx) { _context = ctx; } public void outOfMemory(OutOfMemoryError oom) { try { // prevent multiple parallel shutdowns (when you OOM, you OOM a lot...) if (_context.router().isFinalShutdownInProgress()) return; } catch (OutOfMemoryError oome) {} try { // Only do this once if (_wasCalled.getAndSet(true)) return; } catch (OutOfMemoryError oome) {} try { // boost priority to help us shut down // this may or may not do anything... Thread.currentThread().setPriority(Thread.MAX_PRIORITY - 1); } catch (OutOfMemoryError oome) {} try { Router.clearCaches(); } catch (OutOfMemoryError oome) {} Log log = null; try { log = _context.logManager().getLog(Router.class); log.log(Log.CRIT, "Thread ran out of memory, shutting down I2P", oom); log.log(Log.CRIT, "free mem: " + Runtime.getRuntime().freeMemory() + " total mem: " + Runtime.getRuntime().totalMemory()); // Can't find any System property or wrapper property that gives // you the actual config file path, have to guess String path; if (SystemVersion.isLinuxService()) { if (SystemVersion.isGentoo()) path = "/usr/share/i2p"; else path = "/etc/i2p"; } else { path = _context.getBaseDir().toString(); } if (_context.hasWrapper()) { log.log(Log.CRIT, "To prevent future shutdowns, increase wrapper.java.maxmemory in " + path + File.separatorChar + "wrapper.config"); } else if (!SystemVersion.isWindows()) { log.log(Log.CRIT, "To prevent future shutdowns, increase MAXMEMOPT in " + path + File.separatorChar + "runplain.sh or /usr/bin/i2prouter-nowrapper"); } else { log.log(Log.CRIT, "To prevent future shutdowns, run the restartable version of I2P, and increase wrapper.java.maxmemory in " + path + File.separatorChar + "wrapper.config"); } } catch (OutOfMemoryError oome) {} try { ThreadDump.dump(_context, 1); } catch (OutOfMemoryError oome) {} try { _context.router().eventLog().addEvent(EventLog.OOM); } catch (OutOfMemoryError oome) {} try { _context.router().shutdown(Router.EXIT_OOM); } catch (OutOfMemoryError oome) {} } }