diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java
index 827e0c457e6ef9b474e5a32148aafef42848902a..254db3179d4a8ad2d7ed3a55e13f5d775c449173 100644
--- a/router/java/src/net/i2p/router/Router.java
+++ b/router/java/src/net/i2p/router/Router.java
@@ -796,6 +796,16 @@ public class Router {
         _isAlive = false;
         _context.random().saveSeed();
         I2PThread.removeOOMEventListener(_oomListener);
+        // Run the shutdown hooks first in case they want to send some goodbye messages
+        // Maybe we need a delay after this too?
+        try {
+            for (Iterator iter = _shutdownTasks.iterator(); iter.hasNext(); ) {
+                Runnable task = (Runnable)iter.next();
+                task.run();
+            }
+        } catch (Throwable t) {
+            _log.log(Log.CRIT, "Error running shutdown task", t);
+        }
         try { _context.jobQueue().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the job queue", t); }
         //try { _context.adminManager().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the admin manager", t); }        
         try { _context.statPublisher().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the stats manager", t); }
@@ -811,14 +821,6 @@ public class Router {
         try { _sessionKeyPersistenceHelper.shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the session key manager", t); }
         RouterContext.listContexts().remove(_context);
         dumpStats();
-        try {
-            for (Iterator iter = _shutdownTasks.iterator(); iter.hasNext(); ) {
-                Runnable task = (Runnable)iter.next();
-                task.run();
-            }
-        } catch (Throwable t) {
-            _log.log(Log.CRIT, "Error running shutdown task", t);
-        }
         finalShutdown(exitCode);
     }