diff --git a/core/java/src/net/i2p/util/I2PAppThread.java b/core/java/src/net/i2p/util/I2PAppThread.java
index c3de5c87acb5650b57d0b486b85509af3b251d4f..ebbe6c06e1a55cf6da2905876f95a95cc78fb846 100644
--- a/core/java/src/net/i2p/util/I2PAppThread.java
+++ b/core/java/src/net/i2p/util/I2PAppThread.java
@@ -14,10 +14,13 @@ import java.util.Set;
 import java.util.concurrent.CopyOnWriteArraySet;
 
 /**
- * Like I2PThread but with per-thread OOM listeners,
+ * Like {@link I2PThread} but with per-thread OOM listeners,
  * rather than a static router-wide listener list,
  * so that an OOM in an app won't call the router listener
  * to shutdown the whole router.
+ *
+ * This is preferred for application use.
+ * See {@link I2PThread} for features.
  */
 public class I2PAppThread extends I2PThread {
 
diff --git a/core/java/src/net/i2p/util/I2PThread.java b/core/java/src/net/i2p/util/I2PThread.java
index 97041f4ee251cefa8f78c2fd7f125224faa1cbe3..2b4c2a81e9a73b63c00839a5d3f2497c4e381b63 100644
--- a/core/java/src/net/i2p/util/I2PThread.java
+++ b/core/java/src/net/i2p/util/I2PThread.java
@@ -14,63 +14,53 @@ import java.util.Set;
 import java.util.concurrent.CopyOnWriteArraySet;
 
 /**
- * In case its useful later...
- * (e.g. w/ native programatic thread dumping, etc)
- *
- * As of 0.9.21, I2PThreads are initialized to NORM_PRIORITY
- * (not the priority of the creating thread).
+ * Preferred over {@link Thread} for all router uses.
+ * For applications, {@link I2PAppThread} is preferred.
+ * <p>
+ * Provides the following features:
+ * <ul>
+ * <li>Logging to wrapper log on unexpected termination in {@link #run()}.
+ * <li>Notification of OOM to registered listener (the router),
+ *     which will cause logging to the wrapper log and a router restart
+ * <li>Catching and logging "OOM" caused by thread limit in {@link #start()}
+ *     with distint message, and does not call the OOM listener.
+ * <li>As of 0.9.21, initialization to NORM_PRIORITY
+ *     (not the priority of the creating thread).
+ * </ul>
  */
 public class I2PThread extends Thread {
-    /**
-     *  Non-static to avoid refs to old context in Android.
-     *  Probably should just remove all the logging though.
-     *  Logging removed, too much trouble with extra contexts
-     */
-    //private volatile Log _log;
+
     private static final Set<OOMEventListener> _listeners = new CopyOnWriteArraySet<OOMEventListener>();
-    //private String _name;
-    //private Exception _createdBy;
 
     public I2PThread() {
         super();
         setPriority(NORM_PRIORITY);
-        //if ( (_log == null) || (_log.shouldLog(Log.DEBUG)) )
-        //    _createdBy = new Exception("Created by");
     }
 
     public I2PThread(String name) {
         super(name);
         setPriority(NORM_PRIORITY);
-        //if ( (_log == null) || (_log.shouldLog(Log.DEBUG)) )
-        //    _createdBy = new Exception("Created by");
     }
 
     public I2PThread(Runnable r) {
         super(r);
         setPriority(NORM_PRIORITY);
-        //if ( (_log == null) || (_log.shouldLog(Log.DEBUG)) )
-        //    _createdBy = new Exception("Created by");
     }
 
     public I2PThread(Runnable r, String name) {
         super(r, name);
         setPriority(NORM_PRIORITY);
-        //if ( (_log == null) || (_log.shouldLog(Log.DEBUG)) )
-        //    _createdBy = new Exception("Created by");
     }
+
     public I2PThread(Runnable r, String name, boolean isDaemon) {
         super(r, name);
 	setDaemon(isDaemon);
         setPriority(NORM_PRIORITY);
-        //if ( (_log == null) || (_log.shouldLog(Log.DEBUG)) )
-        //    _createdBy = new Exception("Created by");
     }
     
     public I2PThread(ThreadGroup g, Runnable r) {
         super(g, r);
         setPriority(NORM_PRIORITY);
-        //if ( (_log == null) || (_log.shouldLog(Log.DEBUG)) )
-        //    _createdBy = new Exception("Created by");
     }
 
     /**
@@ -81,17 +71,6 @@ public class I2PThread extends Thread {
         setPriority(NORM_PRIORITY);
     }
 
-/****
-    private void log(int level, String msg) { log(level, msg, null); }
-
-    private void log(int level, String msg, Throwable t) {
-        // we cant assume log is created
-        if (_log == null) _log = new Log(I2PThread.class);
-        if (_log.shouldLog(level))
-            _log.log(level, msg, t);
-    }
-****/
-    
     /**
      *  Overridden to provide useful info to users on OOM, and to prevent
      *  shutting down the whole JVM for what is most likely not a heap issue.
@@ -117,19 +96,9 @@ public class I2PThread extends Thread {
     
     @Override
     public void run() {
-        //_name = Thread.currentThread().getName();
-        //log(Log.INFO, "New thread started" + (isDaemon() ? " (daemon): " : ": ") + _name, _createdBy);
         try {
             super.run();
         } catch (Throwable t) {
-          /****
-            try {
-                log(Log.CRIT, "Thread terminated unexpectedly: " + getName(), t);
-            } catch (Throwable woof) {
-                System.err.println("Died within the OOM itself");
-                t.printStackTrace();
-            }
-          ****/
             if (t instanceof OutOfMemoryError) {
                 fireOOM((OutOfMemoryError)t);
             } else {
@@ -137,18 +106,8 @@ public class I2PThread extends Thread {
                 t.printStackTrace();
             }
         }
-        // This creates a new I2PAppContext after it was deleted
-        // in Router.finalShutdown() via RouterContext.killGlobalContext()
-        //log(Log.INFO, "Thread finished normally: " + _name);
     }
     
-/****
-    protected void finalize() throws Throwable {
-        //log(Log.DEBUG, "Thread finalized: " + _name);
-        super.finalize();
-    }
-****/
-    
     protected void fireOOM(OutOfMemoryError oom) {
         for (OOMEventListener listener : _listeners)
             listener.outOfMemory(oom);