diff --git a/android/src/net/i2p/router/I2PAndroid.java b/android/src/net/i2p/router/I2PAndroid.java
index ed626639ceeee57d5ab0e08dbfa20c2dab7b252c..88d522dd632b00279f28caf8038f1817b715296e 100644
--- a/android/src/net/i2p/router/I2PAndroid.java
+++ b/android/src/net/i2p/router/I2PAndroid.java
@@ -69,7 +69,7 @@ public class I2PAndroid extends Activity
 
         // from routerconsole ContextHelper
         List contexts = RouterContext.listContexts();
-        if ( (contexts == null) || (contexts.size() <= 0) ) 
+        if ( (contexts == null) || (contexts.isEmpty()) ) 
             throw new IllegalStateException("No contexts. This is usually because the router is either starting up or shutting down.");
         RouterContext ctx = (RouterContext)contexts.get(0);
 
diff --git a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java
index 9804da5d6620dd4ba254f6645c1cebb057b2adcd..35139420c2007741ef77b10340095c58cfc93d50 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java
@@ -355,7 +355,7 @@ public class I2PSnarkUtil {
         while (tok.hasMoreTokens())
             rv.add(tok.nextToken());
         
-        if (rv.size() <= 0)
+        if (rv.isEmpty())
             return null;
         return rv;
     }
diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java b/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java
index 3326a60860427989f59cd9690277a4910c133802..81525a1ea82d2d7405f7ca60b824889a0fa0e6d2 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java
@@ -142,7 +142,7 @@ class PeerConnectionOut implements Runnable
                             it.remove();
                           }
                       }
-                    if (m == null && sendQueue.size() > 0) {
+                    if (m == null && !sendQueue.isEmpty()) {
                       m = (Message)sendQueue.remove(0);
                       SimpleTimer.getInstance().removeEvent(m.expireEvent);
                     }
diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java
index af567efc34308143d264d3ecc2506a2784106838..c3070913eedfd41601309d730b53ab9e7ec41956 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java
@@ -272,7 +272,7 @@ public class PeerCoordinator implements PeerListener
         peerCount = 0;
       }
 
-    while (removed.size() > 0) {
+    while (!removed.isEmpty()) {
         Peer peer = (Peer)removed.remove(0);
         peer.disconnect();
         removePeerFromPieces(peer);
@@ -428,7 +428,7 @@ public class PeerCoordinator implements PeerListener
               }
           }
 
-        while (uploaders < maxUploaders && interested.size() > 0)
+        while (uploaders < maxUploaders && !interested.isEmpty())
           {
             Peer peer = (Peer)interested.remove(0);
             if (_log.shouldLog(Log.DEBUG))
diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
index d0d9a3bd8476d59c95c291ca3ddcc66016ab7683..33f74707ec0c884693ed6d56aa03a704c7e8d3b4 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
@@ -30,7 +30,7 @@ public class SnarkManager implements Snark.CompleteListener {
     public static SnarkManager instance() { return _instance; }
     
     /** map of (canonical) filename to Snark instance (unsynchronized) */
-    private final Map _snarks;
+    private final Map<String, Snark> _snarks;
     private final Object _addSnarkLock;
     private /* FIXME final FIXME */ File _configFile;
     private Properties _config;
@@ -394,7 +394,7 @@ public class SnarkManager implements Snark.CompleteListener {
     private static final int MAX_FILES_PER_TORRENT = 512;
     
     /** set of filenames that we are dealing with */
-    public Set listTorrentFiles() { synchronized (_snarks) { return new HashSet(_snarks.keySet()); } }
+    public Set<String> listTorrentFiles() { synchronized (_snarks) { return new HashSet(_snarks.keySet()); } }
     /**
      * Grab the torrent given the (canonical) filename
      */
diff --git a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java
index e5d553462f91041e07351fbb61d8f2d9fcfc579e..8822bba931af1eaa86ecacd4ea48b49e2bd426a1 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java
@@ -163,7 +163,7 @@ public class TrackerClient extends I2PAppThread
         }
     }
 
-    if (tlist.size() <= 0) {
+    if (tlist.isEmpty()) {
         // FIXME really need to get this message to the gui
         stop = true;
         _log.error("No valid trackers for infoHash: " + infoHash);
diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
index 2e9d1425f39f1de2bc41df15015ee5b05e76912d..465f4f908e8a3156350901ae64be15d9418cbef1 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
@@ -7,6 +7,7 @@ import java.io.IOException;
 import java.io.PrintWriter;
 import java.text.Collator;
 import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.List;
@@ -176,7 +177,7 @@ public class I2PSnarkServlet extends Default {
         String uri = req.getRequestURI();
         out.write(TABLE_HEADER);
         out.write(_("Status"));
-        if (_manager.util().connected() && snarks.size() > 0) {
+        if (_manager.util().connected() && !snarks.isEmpty()) {
             out.write(" (<a href=\"");
             out.write(req.getRequestURI());
             if (peerParam != null) {
@@ -210,7 +211,7 @@ public class I2PSnarkServlet extends Default {
             out.write("\">");
             out.write(_("Stop All"));
             out.write("</a>");
-        } else if (snarks.size() > 0) {
+        } else if (!snarks.isEmpty()) {
             out.write("<a href=\"" + uri + "?action=StartAll&nonce=" + _nonce +
                       "\" title=\"");
             out.write(_("Start all torrents and the I2P tunnel"));
@@ -228,7 +229,7 @@ public class I2PSnarkServlet extends Default {
             displaySnark(out, snark, uri, i, stats, showPeers, showDebug);
         }
 
-        if (snarks.size() <= 0) {
+        if (snarks.isEmpty()) {
             out.write("<tr class=\"snarkTorrentEven\">" +
                       "<td class=\"snarkTorrentEven\" align=\"center\"" +
                       " colspan=\"8\"><i>");
@@ -485,11 +486,34 @@ public class I2PSnarkServlet extends Default {
         }
     }
     
-    private List getSortedSnarks(HttpServletRequest req) {
-        Set files = _manager.listTorrentFiles();
-        TreeSet fileNames = new TreeSet(Collator.getInstance()); // sorts it alphabetically
+    /**
+     *  Sort alphabetically in current locale, ignore case, ignore leading "the "
+     *  (I guess this is worth it, a lot of torrents start with "The "
+     *  These are full path names which makes it harder
+     *  @since 0.7.14
+     */
+    private class TorrentNameComparator implements Comparator<String> {
+        private final Comparator collator = Collator.getInstance();
+        private final String skip = _manager.getDataDir().getAbsolutePath() + File.separator;
+
+        public int compare(String l, String r) {
+            if (l.startsWith(skip))
+                l = l.substring(skip.length());
+            if (r.startsWith(skip))
+                r = r.substring(skip.length());
+            if (l.toLowerCase().startsWith("the "))
+                l = l.substring(4);
+            if (r.toLowerCase().startsWith("the "))
+                r = r.substring(4);
+            return collator.compare(l, r);
+        }
+    }
+
+    private List<Snark> getSortedSnarks(HttpServletRequest req) {
+        Set<String> files = _manager.listTorrentFiles();
+        TreeSet<String> fileNames = new TreeSet(new TorrentNameComparator());
         fileNames.addAll(files);
-        ArrayList rv = new ArrayList(fileNames.size());
+        ArrayList<Snark> rv = new ArrayList(fileNames.size());
         for (Iterator iter = fileNames.iterator(); iter.hasNext(); ) {
             String name = (String)iter.next();
             Snark snark = _manager.getTorrent(name);
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClient.java
index 8fc2970ad2c942c19408093c6fbdcf2d0b431eeb..89339bf04c3e320e1c4ae78ca171562780a29056 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClient.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClient.java
@@ -54,7 +54,7 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
             }
         }
 
-        if (dests.size() <= 0) {
+        if (dests.isEmpty()) {
             l.log("No target destinations found");
             notifyEvent("openClientResult", "error");
             return;
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java
index b3ffcdb45e1cb15542a7af309357a3c1b70ac44b..398fd73495d336e6a3c78b70d102cbfd0c235b58 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java
@@ -641,7 +641,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
             while (open) {
                 try {
                     synchronized (_waitingSockets) {
-                        if (_waitingSockets.size() <= 0)
+                        if (_waitingSockets.isEmpty())
                             _waitingSockets.wait();
                         else
                             s = (Socket)_waitingSockets.remove(0);
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java
index 2002ece32cab3f181e0f822f30764e67b20e50aa..421ec9e7ff17d434576d40fc5e3744231c57f9a4 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java
@@ -508,7 +508,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
                         }
 
                         line = method + " " + request.substring(pos);
-                    } else if (host.toLowerCase().equals("localhost") || host.equals("127.0.0.1")) {
+                    } else if (host.toLowerCase().equals("localhost") || host.equals("127.0.0.1") ||
+                               host.startsWith("192.168.")) {
+                        // if somebody is trying to get to 192.168.example.com, oh well
                         if (out != null) {
                             out.write(getErrorPage("localhost", ERR_LOCALHOST));
                             writeFooter(out);
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java
index fed00886e6f6f04a4b755c4a0b8535e300c8cc48..a7fbcf37b5a038b17deb4467753aa8f9dbcea26f 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java
@@ -61,7 +61,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
             }
         }
 
-        if (dests.size() <= 0) {
+        if (dests.isEmpty()) {
             l.log("No target destinations found");
             notifyEvent("openClientResult", "error");
             return;
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelControllerGroup.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelControllerGroup.java
index 4250dedd07da820cb25351fc6f94e0841a9990cc..112f0d62f06544973445ce97c2e37f023a4a9d5e 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelControllerGroup.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelControllerGroup.java
@@ -329,7 +329,7 @@ public class TunnelControllerGroup {
             Set owners = (Set)_sessions.get(session);
             if (owners != null) {
                 owners.remove(controller);
-                if (owners.size() <= 0) {
+                if (owners.isEmpty()) {
                     if (_log.shouldLog(Log.INFO))
                         _log.info("After releasing session " + session + " by " + controller + ", no more owners remain");
                     shouldClose = true;
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS4aServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS4aServer.java
index ef88102cf08ed63ac18a9b67c4ca245e5abf219e..55feadf2189e8e004696355e2f54031bf3446fcc 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS4aServer.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS4aServer.java
@@ -224,7 +224,7 @@ public class SOCKS4aServer extends SOCKSServer {
                 throw new SOCKSException(err);
             } else {
                 List<String> proxies = t.getProxies(connPort);
-                if (proxies == null || proxies.size() <= 0) {
+                if (proxies == null || proxies.isEmpty()) {
                     String err = "No outproxy configured for port " + connPort + " and no default configured either - host: " + connHostName;
                     _log.error(err);
                     try {
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java
index 103f6a945485845357b57c6d1b483c91f5a9ec01..c87a320dd3c17cbdbfd4fce37f7424bad303d621 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java
@@ -332,7 +332,7 @@ public class SOCKS5Server extends SOCKSServer {
                 throw new SOCKSException(err);
             } else {
                 List<String> proxies = t.getProxies(connPort);
-                if (proxies == null || proxies.size() <= 0) {
+                if (proxies == null || proxies.isEmpty()) {
                     String err = "No outproxy configured for port " + connPort + " and no default configured either";
                     _log.error(err);
                     try {
diff --git a/apps/jetty/java/src/org/mortbay/http/HttpContext.java b/apps/jetty/java/src/org/mortbay/http/HttpContext.java
index 061d3ad17f971f853ebc3216bef59952bbcbc329..1ae1a08b6ef6748736519fd16afab4819b43e9f5 100644
--- a/apps/jetty/java/src/org/mortbay/http/HttpContext.java
+++ b/apps/jetty/java/src/org/mortbay/http/HttpContext.java
@@ -1301,7 +1301,7 @@ public class HttpContext extends Container
 
         List scss= _constraintMap.getMatches(pathInContext);
         String pattern=null;
-        if (scss != null && scss.size() > 0)
+        if (scss != null && !scss.isEmpty())
         {
             Object constraints= null;
 
diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocketImpl.java b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocketImpl.java
index 2e0609f5640a9c618ce614ffa016c6ee32ba40e0..c1378b3a13564d0f8465e6ad94da88e36fe1fa1c 100644
--- a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocketImpl.java
+++ b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocketImpl.java
@@ -69,7 +69,7 @@ class I2PServerSocketImpl implements I2PServerSocket {
         I2PSocket ret = null;
         
         while ( (ret == null) && (!closing) ){
-            while (pendingSockets.size() <= 0) {
+            while (pendingSockets.isEmpty()) {
                 if (closing) throw new ConnectException("I2PServerSocket closed");
                 try {
                     synchronized(socketAddedLock) {
@@ -78,7 +78,7 @@ class I2PServerSocketImpl implements I2PServerSocket {
                 } catch (InterruptedException ie) {}
             }
             synchronized (pendingSockets) {
-                if (pendingSockets.size() > 0) {
+                if (!pendingSockets.isEmpty()) {
                     ret = (I2PSocket)pendingSockets.remove(0);
                 }
             } 
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/CSSHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/CSSHelper.java
index ffc77f71bb754ef575a648c574e00566b618814e..785acce6d5a6b2be1dba6e776300926f84137653 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/CSSHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/CSSHelper.java
@@ -19,6 +19,9 @@ public class CSSHelper extends HelperBase {
         if (userAgent != null && userAgent.contains("MSIE")) {
             url += FORCE + "/";
         } else {
+            // This is the first thing to use _context on most pages
+            if (_context == null)
+                throw new IllegalStateException("No contexts. This is usually because the router is either starting up or shutting down.");
             String theme = _context.getProperty(PROP_THEME_NAME, DEFAULT_THEME);
             url += theme + "/";
         }
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java
index 6b172c156fc9d8818de2840dcba643d3c88a3f50..049b5a02a974c62cc17db955914775680783f494 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java
@@ -88,7 +88,7 @@ public class ConfigClientsHelper extends HelperBase {
                 String app = name.substring(PluginStarter.PREFIX.length(), name.lastIndexOf(PluginStarter.ENABLED));
                 String val = props.getProperty(name);
                 Properties appProps = PluginStarter.pluginProperties(_context, app);
-                if (appProps.size() <= 0)
+                if (appProps.isEmpty())
                     continue;
                 StringBuilder desc = new StringBuilder(256);
                 desc.append("<table border=\"0\">")
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigStatsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigStatsHelper.java
index 5c22ed1b1e2530fad647976a6a38e63121566e9a..07c0f3e0f7d415f855561dc822c93977cb99d55b 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigStatsHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigStatsHelper.java
@@ -70,7 +70,7 @@ public class ConfigStatsHelper extends HelperBase {
      * @return true if a valid stat is available, otherwise false
      */
     public boolean hasMoreStats() {
-        if (_stats.size() <= 0)
+        if (_stats.isEmpty())
             return false;
         _currentIsGraphed = false;
         _currentStatName = (String)_stats.remove(0);
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigTunnelsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigTunnelsHelper.java
index 2be5a4a00b5427a391aceae02241e96d5924c493..4d007e9d76162b5b9356ea4c05d91167da4d80ed 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigTunnelsHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigTunnelsHelper.java
@@ -163,7 +163,7 @@ public class ConfigTunnelsHelper extends HelperBase {
         // TunnelPoolOptions, so make the boxes readonly.
         // And let's not display them at all unless they have contents, which should be rare.
         Properties props = in.getUnknownOptions();
-        if (props.size() > 0) {
+        if (!props.isEmpty()) {
             buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Inbound options") + ":</td>\n" +
                        "<td colspan=\"2\" align=\"center\"><input name=\"").append(index);
             buf.append(".inboundOptions\" type=\"text\" size=\"32\" disabled=\"true\" " +
@@ -176,7 +176,7 @@ public class ConfigTunnelsHelper extends HelperBase {
             buf.append("\"></td></tr>\n");
         }
         props = out.getUnknownOptions();
-        if (props.size() > 0) {
+        if (!props.isEmpty()) {
             buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Outbound options") + ":</td>\n" +
                        "<td colspan=\"2\" align=\"center\"><input name=\"").append(index);
             buf.append(".outboundOptions\" type=\"text\" size=\"32\" disabled=\"true\" " +
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ContextHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ContextHelper.java
index 0aa250654837e9ca144ca9fd79496ffb86e5e3b5..aab5a2ce9b044ed76ef6cb5eb2cbb7b6304500b1 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ContextHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ContextHelper.java
@@ -6,9 +6,11 @@ import net.i2p.data.Hash;
 import net.i2p.router.RouterContext;
 
 class ContextHelper {
+
+    /** @throws IllegalStateException if no context available */
     public static RouterContext getContext(String contextId) {
         List contexts = RouterContext.listContexts();
-        if ( (contexts == null) || (contexts.size() <= 0) ) 
+        if ( (contexts == null) || (contexts.isEmpty()) ) 
             throw new IllegalStateException("No contexts. This is usually because the router is either starting up or shutting down.");
         if ( (contextId == null) || (contextId.trim().length() <= 0) )
             return (RouterContext)contexts.get(0);
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java
index bb131fe75f6a503324f06f26c4fcf57a365ca460..f064c5abcd59f32188f4b18fc65bd778a518d4fd 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java
@@ -85,16 +85,16 @@ public class FormHandler {
     public String getAllMessages() { 
         validate();
         process();
-        if (_errors.size() <= 0 && _notices.size() <= 0)
+        if (_errors.isEmpty() && _notices.isEmpty())
             return "";
         StringBuilder buf = new StringBuilder(512);
         buf.append("<div class=\"messages\" id=\"messages\"><p>");
-        if (_errors.size() > 0) {
+        if (!_errors.isEmpty()) {
             buf.append("<span class=\"error\">");
             buf.append(render(_errors));
             buf.append("</span>");
         }
-        if (_notices.size() > 0) {
+        if (!_notices.isEmpty()) {
             buf.append("<span class=\"notice\">");
             buf.append(render(_notices));
             buf.append("</span>");
@@ -174,8 +174,8 @@ public class FormHandler {
         }
     }
     
-    private String render(List<String> source) {
-        if (source.size() <= 0) {
+    private static String render(List<String> source) {
+        if (source.isEmpty()) {
             return "";
         } else {
             StringBuilder buf = new StringBuilder(512);
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java
index effcca6bf02b0ca4c64e6a7e4f9d1d480e38f886..d360e346ebb7d781a84d6ae8a48dd5762d814e49 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java
@@ -185,7 +185,7 @@ public class NetDbRenderer {
         buf.append("<table border=\"0\" cellspacing=\"30\"><tr><th colspan=\"3\">").append(_("Network Database Router Statistics")).append("</th><tr><td>");
         // versions table
         List<String> versionList = new ArrayList(versions.objects());
-        if (versionList.size() > 0) {
+        if (!versionList.isEmpty()) {
             Collections.sort(versionList, Collections.reverseOrder(new VersionComparator()));
             buf.append("<table>\n");
             buf.append("<tr><th>" + _("Version") + "</th><th>" + _("Count") + "</th></tr>\n");
@@ -217,7 +217,7 @@ public class NetDbRenderer {
 
         // country table
         List<String> countryList = new ArrayList(countries.objects());
-        if (countryList.size() > 0) {
+        if (!countryList.isEmpty()) {
             Collections.sort(countryList, new CountryComparator());
             buf.append("<table>\n");
             buf.append("<tr><th align=\"left\">" + _("Country") + "</th><th>" + _("Count") + "</th></tr>\n");
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/NewsFetcher.java b/apps/routerconsole/java/src/net/i2p/router/web/NewsFetcher.java
index e5c0ef9a17f1fd2299df2b70b42f13e879213f65..f7ac8cb9421cbb23cbd63c12768c52c769ad1564 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/NewsFetcher.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/NewsFetcher.java
@@ -322,7 +322,7 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
                 handler = new UpdateHandler((RouterContext)_context);
             } else {
                 List contexts = RouterContext.listContexts();
-                if (contexts.size() > 0)
+                if (!contexts.isEmpty())
                     handler = new UpdateHandler((RouterContext)contexts.get(0));
                 else
                     _log.log(Log.CRIT, "No router context to update with?");
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java b/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java
index 3c4c4fd9b219addfc449c8127639e6b76920f149..22062cb7f1595f714c7f69e613cdc6b4e542e54c 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java
@@ -2,6 +2,7 @@ package net.i2p.router.web;
 
 import java.io.File;
 import java.io.IOException;
+import java.lang.ClassLoader;
 import java.lang.reflect.Method;
 import java.net.URL;
 import java.net.URLClassLoader;
@@ -48,6 +49,7 @@ public class PluginStarter implements Runnable {
                                                       "midnight" };
     private static Map<String, ThreadGroup> pluginThreadGroups = new ConcurrentHashMap<String, ThreadGroup>();   // one thread group per plugin (map key=plugin name)
     private static Map<String, Collection<Job>> pluginJobs = new ConcurrentHashMap<String, Collection<Job>>();
+    private static Map<String, ClassLoader> _clCache = new ConcurrentHashMap();
 
     public PluginStarter(RouterContext ctx) {
         _context = ctx;
@@ -87,7 +89,7 @@ public class PluginStarter implements Runnable {
      */
     static boolean startPlugin(RouterContext ctx, String appName) throws Exception {
         Log log = ctx.logManager().getLog(PluginStarter.class);
-        File pluginDir = new File(ctx.getAppDir(), PluginUpdateHandler.PLUGIN_DIR + '/' + appName);
+        File pluginDir = new File(ctx.getConfigDir(), PluginUpdateHandler.PLUGIN_DIR + '/' + appName);
         if ((!pluginDir.exists()) || (!pluginDir.isDirectory())) {
             log.error("Cannot start nonexistent plugin: " + appName);
             return false;
@@ -195,7 +197,7 @@ public class PluginStarter implements Runnable {
      */
     static boolean stopPlugin(RouterContext ctx, String appName) throws Exception {
         Log log = ctx.logManager().getLog(PluginStarter.class);
-        File pluginDir = new File(ctx.getAppDir(), PluginUpdateHandler.PLUGIN_DIR + '/' + appName);
+        File pluginDir = new File(ctx.getConfigDir(), PluginUpdateHandler.PLUGIN_DIR + '/' + appName);
         if ((!pluginDir.exists()) || (!pluginDir.isDirectory())) {
             log.error("Cannot stop nonexistent plugin: " + appName);
             return false;
@@ -244,7 +246,7 @@ public class PluginStarter implements Runnable {
     /** @return true on success - caller should call stopPlugin() first */
     static boolean deletePlugin(RouterContext ctx, String appName) throws Exception {
         Log log = ctx.logManager().getLog(PluginStarter.class);
-        File pluginDir = new File(ctx.getAppDir(), PluginUpdateHandler.PLUGIN_DIR + '/' + appName);
+        File pluginDir = new File(ctx.getConfigDir(), PluginUpdateHandler.PLUGIN_DIR + '/' + appName);
         if ((!pluginDir.exists()) || (!pluginDir.isDirectory())) {
             log.error("Cannot delete nonexistent plugin: " + appName);
             return false;
@@ -287,7 +289,7 @@ public class PluginStarter implements Runnable {
 
     /** plugin.config */
     public static Properties pluginProperties(I2PAppContext ctx, String appName) {
-        File cfgFile = new File(ctx.getAppDir(), PluginUpdateHandler.PLUGIN_DIR + '/' + appName + '/' + "plugin.config");
+        File cfgFile = new File(ctx.getConfigDir(), PluginUpdateHandler.PLUGIN_DIR + '/' + appName + '/' + "plugin.config");
         Properties rv = new Properties();
         try {
             DataHelper.loadProps(rv, cfgFile);
@@ -322,7 +324,7 @@ public class PluginStarter implements Runnable {
      */
     public static List<String> getPlugins() {
         List<String> rv = new ArrayList();
-        File pluginDir = new File(I2PAppContext.getGlobalContext().getAppDir(), PluginUpdateHandler.PLUGIN_DIR);
+        File pluginDir = new File(I2PAppContext.getGlobalContext().getConfigDir(), PluginUpdateHandler.PLUGIN_DIR);
         File[] files = pluginDir.listFiles();
         if (files == null)
             return rv;
@@ -405,6 +407,8 @@ public class PluginStarter implements Runnable {
                     argVal[i] = argVal[i].replace("$PLUGIN", pluginDir.getAbsolutePath());
                 }
             }
+
+            ClassLoader cl = null;
             if (app.classpath != null) {
                 String cp = new String(app.classpath);
                 if (cp.indexOf("$") >= 0) {
@@ -412,22 +416,41 @@ public class PluginStarter implements Runnable {
                     cp = cp.replace("$CONFIG", ctx.getConfigDir().getAbsolutePath());
                     cp = cp.replace("$PLUGIN", pluginDir.getAbsolutePath());
                 }
-                addToClasspath(cp, app.clientName, log);
+
+                // Old way - add for the whole JVM
+                //addToClasspath(cp, app.clientName, log);
+
+                // New way - add only for this client
+                // We cache the ClassLoader we start the client with, so
+                // we can reuse it for stopping and uninstalling.
+                // If we don't, the client won't be able to find its
+                // static members.
+                String clCacheKey = pluginName + app.className + app.args;
+                if (!action.equals("start"))
+                    cl = _clCache.get(clCacheKey);
+                if (cl == null) {
+                    URL[] urls = classpathToURLArray(cp, app.clientName, log);
+                    if (urls != null) {
+                        cl = new URLClassLoader(urls, ClassLoader.getSystemClassLoader());
+                        if (action.equals("start"))
+                            _clCache.put(clCacheKey, cl);
+                    }
+                }
             }
 
             if (app.delay < 0 && action.equals("start")) {
                 // this will throw exceptions
-                LoadClientAppsJob.runClientInline(app.className, app.clientName, argVal, log);
+                LoadClientAppsJob.runClientInline(app.className, app.clientName, argVal, log, cl);
             } else if (app.delay == 0 || !action.equals("start")) {
                 // quick check, will throw ClassNotFoundException on error
-                LoadClientAppsJob.testClient(app.className);
+                LoadClientAppsJob.testClient(app.className, cl);
                 // run this guy now
-                LoadClientAppsJob.runClient(app.className, app.clientName, argVal, log, pluginThreadGroup);
+                LoadClientAppsJob.runClient(app.className, app.clientName, argVal, log, pluginThreadGroup, cl);
             } else {
                 // quick check, will throw ClassNotFoundException on error
-                LoadClientAppsJob.testClient(app.className);
+                LoadClientAppsJob.testClient(app.className, cl);
                 // wait before firing it up
-                Job job = new LoadClientAppsJob.DelayedRunClient(ctx, app.className, app.clientName, argVal, app.delay, pluginThreadGroup);
+                Job job = new LoadClientAppsJob.DelayedRunClient(ctx, app.className, app.clientName, argVal, app.delay, pluginThreadGroup, cl);
                 ctx.jobQueue().addJob(job);
                 pluginJobs.get(pluginName).add(job);
             }
@@ -470,6 +493,7 @@ public class PluginStarter implements Runnable {
      *  but I don't see how to make it magically get used for everything.
      *  So add this to the whole JVM's classpath.
      */
+/******
     private static void addToClasspath(String classpath, String clientName, Log log) {
         StringTokenizer tok = new StringTokenizer(classpath, ",");
         while (tok.hasMoreTokens()) {
@@ -488,6 +512,33 @@ public class PluginStarter implements Runnable {
             }
         }
     }
+*****/
+
+    /**
+     *  @return null if no valid elements
+     */
+    private static URL[] classpathToURLArray(String classpath, String clientName, Log log) {
+        StringTokenizer tok = new StringTokenizer(classpath, ",");
+        List<URL> urls = new ArrayList();
+        while (tok.hasMoreTokens()) {
+            String elem = tok.nextToken().trim();
+            File f = new File(elem);
+            if (!f.isAbsolute()) {
+                log.error("Plugin client " + clientName + " classpath element is not absolute: " + f);
+                continue;
+            }
+            try {
+                urls.add(f.toURI().toURL());
+                if (log.shouldLog(Log.WARN))
+                    log.warn("INFO: Adding plugin to classpath: " + f);
+            } catch (Exception e) {
+                log.error("Plugin client " + clientName + " bad classpath element: " + f, e);
+            }
+        }
+        if (urls.isEmpty())
+            return null;
+        return urls.toArray(new URL[urls.size()]);
+    }
 
     /**
      *  http://jimlife.wordpress.com/2007/12/19/java-adding-new-classpath-at-runtime/
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/PluginUpdateHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/PluginUpdateHandler.java
index e028ee3cdc53f010e722f8465c8c5ef0ed53cfc6..8ba4708405ab6a491dbad50520acfcebcb7b6177 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/PluginUpdateHandler.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/PluginUpdateHandler.java
@@ -150,7 +150,7 @@ public class PluginUpdateHandler extends UpdateHandler {
         public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) {
             updateStatus("<b>" + _("Plugin downloaded") + "</b>");
             File f = new File(_updateFile);
-            File appDir = new File(_context.getAppDir(), PLUGIN_DIR);
+            File appDir = new File(_context.getConfigDir(), PLUGIN_DIR);
             if ((!appDir.exists()) && (!appDir.mkdir())) {
                 f.delete();
                 statusDone("<b>" + _("Cannot create plugin directory {0}", appDir.getAbsolutePath()) + "</b>");
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java
index 460db8d1765679bd4c2684d85fefdfc9b660c418..58a6d5c9644dccc70eaff18e6c4c92ff4aa71b20 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java
@@ -75,7 +75,7 @@ public class RouterConsoleRunner {
         _server = new Server();
         boolean rewrite = false;
         Properties props = webAppProperties();
-        if (props.size() <= 0) {
+        if (props.isEmpty()) {
             props.setProperty(PREFIX + ROUTERCONSOLE + ENABLED, "true");
             rewrite = true;
         }
@@ -161,6 +161,7 @@ public class RouterConsoleRunner {
                                "If so, you may ignore this error, or remove the\n" +
                                "\"::1,\" in the \"clientApp.0.args\" line of the clients.config file.\n" +
                                "Exception: " + me);
+            me.printStackTrace();
         }
 
         if (baseHandler != null) {
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ShitlistRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/ShitlistRenderer.java
index b1e3ccf30253f15e7a7c40a13832939c2aa93141..48af67857a049dd109af3a45585371cc73f4c045 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ShitlistRenderer.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ShitlistRenderer.java
@@ -58,7 +58,7 @@ public class ShitlistRenderer {
             else
                 buf.append(_("Banned until restart or in {0}", expireString));
             Set transports = entry.transports;
-            if ( (transports != null) && (transports.size() > 0) )
+            if ( (transports != null) && (!transports.isEmpty()) )
                 buf.append(" on the following transport: ").append(transports);
             if (entry.cause != null) {
                 buf.append("<br>\n");
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java
index e7054ccd99bdd3b7c8fdf930ff18bb40b4098f73..1e61bde4fbeb7ecf3d56b2d58958c07af8c1398b 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java
@@ -373,7 +373,7 @@ public class SummaryHelper extends HelperBase {
         
         StringBuilder buf = new StringBuilder(512);
         buf.append("<h3><a href=\"/i2ptunnel/index.jsp\" target=\"_blank\" title=\"").append(_("Add/remove/edit &amp; control your client and server tunnels")).append("\">").append(_("Local Destinations")).append("</a></h3><hr><div class=\"tunnels\">");
-        if (clients.size() > 0) {
+        if (!clients.isEmpty()) {
             Collections.sort(clients, new AlphaComparator());
             buf.append("<table>");
             
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java
index 101160d41cb2b90fe79d8c4cc33203bf9271ac01..da5305ef0dcd2d97db359cd86da032e01a87d78f 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java
@@ -201,15 +201,17 @@ public class TunnelRenderer {
         out.write("</table>\n");
         if (in != null) {
             List pending = in.listPending();
-            if (pending.size() > 0)
+            if (!pending.isEmpty()) {
                 out.write("<div class=\"statusnotes\"><center><b>" + _("Build in progress") + ": " + pending.size() + " " + _("inbound") + "</b></center></div>\n");
-            live += pending.size();
+                live += pending.size();
+            }
         }
         if (outPool != null) {
             List pending = outPool.listPending();
-            if (pending.size() > 0)
+            if (!pending.isEmpty()) {
                 out.write("<div class=\"statusnotes\"><center><b>" + _("Build in progress") + ": " + pending.size() + " " + _("outbound") + "</b></center></div>\n");
-            live += pending.size();
+                live += pending.size();
+            }
         }
         if (live <= 0)
             out.write("<div class=\"statusnotes\"><center><b>" + _("No tunnels; waiting for the grace period to end.") + "</center></b></div>\n");
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java b/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java
index 1cfc09b4cde5a23001b852b80e04dba5f8e2ff20..0943ea4177293327cdbac18f8ecafcc80418f942 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java
@@ -54,7 +54,7 @@ public class WebAppConfiguration implements WebApplicationContext.Configuration
         I2PAppContext i2pContext = I2PAppContext.getGlobalContext();
         File libDir = new File(i2pContext.getBaseDir(), "lib");
         // FIXME this only works if war is the same name as the plugin
-        File pluginDir = new File(i2pContext.getAppDir(),
+        File pluginDir = new File(i2pContext.getConfigDir(),
                                         PluginUpdateHandler.PLUGIN_DIR + ctxPath);
 
         File dir = libDir;
diff --git a/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java b/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java
index aef2802bd867f9d2ec4f41ec6dd98998ff2f0d26..20d4cacf78edbc8f977f8f14ec66c2ba004c333e 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java
@@ -739,7 +739,7 @@ public class SAMStreamSession {
                 data = null;
                 try {
                     synchronized (_data) {
-                        if (_data.size() > 0) {
+                        if (!_data.isEmpty()) {
                             data = (ByteArray)_data.remove(0);
                         } else if (_shuttingDownGracefully) {
                             /* No data left and shutting down gracefully?
diff --git a/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java
index a44c905430768e70d06c00af3d06385f813d33bd..487f8fdf1fd5a9484ba86247e16f880ba1e2621c 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java
@@ -308,7 +308,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
   protected boolean execDestMessage(String opcode, Properties props) {
 
         if (opcode.equals("GENERATE")) {
-            if (props.size() > 0) {
+            if (!props.isEmpty()) {
                 _log.debug("Properties specified in DEST GENERATE message");
                 return false;
             }
diff --git a/apps/sam/java/src/net/i2p/sam/SAMv2StreamSession.java b/apps/sam/java/src/net/i2p/sam/SAMv2StreamSession.java
index 4197597eb0d56e9f26bcd1cbab60b2669916786b..6b59435d31d87a4220daf7dccbf6b0250c51e319 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMv2StreamSession.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMv2StreamSession.java
@@ -371,7 +371,7 @@ public class SAMv2StreamSession extends SAMStreamSession
 						{
 							synchronized ( _data )
 							{
-								if ( _data.size() > 0 )
+								if ( !_data.isEmpty() )
 								{
 									int formerSize = _dataSize ;
 									data = ( ByteArray ) _data.remove ( 0 );
diff --git a/apps/streaming/java/src/net/i2p/client/streaming/Connection.java b/apps/streaming/java/src/net/i2p/client/streaming/Connection.java
index 2cc1a0cf1f463859b68c8f40720b69b7b3232da9..bc8c923699cf61f225625981264630d36dd046e8 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/Connection.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/Connection.java
@@ -449,7 +449,7 @@ public class Connection {
             }
             _outboundPackets.notifyAll();
         }
-        if ((acked != null) && (acked.size() > 0) )
+        if ((acked != null) && (!acked.isEmpty()) )
             _ackSinceCongestion = true;
         return acked;
     }
diff --git a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java
index 5292b5f09f6ef29a53fe2d1954738469fef41afa..e4a8efbc06209088e9843ba0a7af3c35cdca8ca8 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java
@@ -253,7 +253,7 @@ public class ConnectionPacketHandler {
         else
             return false;
         
-        if ( (acked != null) && (acked.size() > 0) ) {
+        if ( (acked != null) && (!acked.isEmpty()) ) {
             if (_log.shouldLog(Log.DEBUG))
                 _log.debug(acked.size() + " of our packets acked with " + packet);
             // use the highest RTT, since these would likely be bunched together,
diff --git a/apps/streaming/java/src/net/i2p/client/streaming/MessageInputStream.java b/apps/streaming/java/src/net/i2p/client/streaming/MessageInputStream.java
index 38537bc7f37189c55104f4208a74e7839053dc1f..14b304b2688dfcb0e00b7d75f703476294c199d0 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/MessageInputStream.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/MessageInputStream.java
@@ -283,15 +283,15 @@ public class MessageInputStream extends InputStream {
             expiration = _readTimeout + System.currentTimeMillis();
         synchronized (_dataLock) {
             for (int i = 0; i < length; i++) {
-                if ( (_readyDataBlocks.size() <= 0) && (i == 0) ) {
+                if ( (_readyDataBlocks.isEmpty()) && (i == 0) ) {
                     // ok, we havent found anything, so lets block until we get 
                     // at least one byte
                     
-                    while (_readyDataBlocks.size() <= 0) {
+                    while (_readyDataBlocks.isEmpty()) {
                         if (_locallyClosed)
                             throw new IOException("Already closed, you wanker");
                         
-                        if ( (_notYetReadyBlocks.size() <= 0) && (_closeReceived) ) {
+                        if ( (_notYetReadyBlocks.isEmpty()) && (_closeReceived) ) {
                             if (_log.shouldLog(Log.INFO))
                                 _log.info("read(...," + offset + ", " + length + ")[" + i 
                                            + "] got EOF after " + _readTotal + " " + toString());
@@ -322,7 +322,7 @@ public class MessageInputStream extends InputStream {
                                                + ") with nonblocking setup: " + toString());
                                 return i;
                             }
-                            if (_readyDataBlocks.size() <= 0) {
+                            if (_readyDataBlocks.isEmpty()) {
                                 if ( (_readTimeout > 0) && (expiration < System.currentTimeMillis()) ) {
                                     if (_log.shouldLog(Log.INFO))
                                         _log.info("read(...," + offset+", " + length+ ")[" + i 
@@ -334,7 +334,7 @@ public class MessageInputStream extends InputStream {
                     }
                     // we looped a few times then got data, so this pass doesnt count
                     i--;
-                } else if (_readyDataBlocks.size() <= 0) {
+                } else if (_readyDataBlocks.isEmpty()) {
                     if (_log.shouldLog(Log.DEBUG))
                         _log.debug("read(...," + offset+", " + length+ ")[" + i 
                                    + "] no more ready blocks, returning");
diff --git a/apps/streaming/java/src/net/i2p/client/streaming/PacketLocal.java b/apps/streaming/java/src/net/i2p/client/streaming/PacketLocal.java
index 3f856ac73d7b61295c0c9268b9ec5da8e9467087..674ff6179c531fcede87686b12d46b18a5f90823 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/PacketLocal.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/PacketLocal.java
@@ -70,9 +70,9 @@ public class PacketLocal extends Packet implements MessageOutputStream.WriteStat
      * @deprecated I2PSession throws out the tags
      */
     public void setTagsSent(Set tags) { 
-        if (tags != null && tags.size() > 0)
+        if (tags != null && !tags.isEmpty())
             _log.error("Who is sending tags thru the streaming lib? " + tags.size());
-        if ( (_tagsSent != null) && (_tagsSent.size() > 0) && (tags.size() > 0) ) {
+        if ( (_tagsSent != null) && (!_tagsSent.isEmpty()) && (!tags.isEmpty()) ) {
             //int old = _tagsSent.size();
             //_tagsSent.addAll(tags);
             if (!_tagsSent.equals(tags))
@@ -160,7 +160,7 @@ public class PacketLocal extends Packet implements MessageOutputStream.WriteStat
         if (con != null)
             buf.append(" rtt ").append(con.getOptions().getRTT());
         
-        if ( (_tagsSent != null) && (_tagsSent.size() > 0) ) 
+        if ( (_tagsSent != null) && (!_tagsSent.isEmpty()) ) 
             buf.append(" with tags");
 
         if (_ackOn > 0)
diff --git a/apps/susidns/src/java/src/i2p/susi/dns/AddressbookBean.java b/apps/susidns/src/java/src/i2p/susi/dns/AddressbookBean.java
index ce53d99d45be40a0a6feefa79654221a7176acc4..443293886fd1eabf3b474b9c9774b5e89d40ffac 100644
--- a/apps/susidns/src/java/src/i2p/susi/dns/AddressbookBean.java
+++ b/apps/susidns/src/java/src/i2p/susi/dns/AddressbookBean.java
@@ -73,7 +73,7 @@ public class AddressbookBean
 	}
 	public boolean isNotEmpty()
 	{
-		return addressbook != null && addressbook.size() > 0;
+		return addressbook != null && !addressbook.isEmpty();
 	}
 	public AddressbookBean()
 	{
@@ -89,7 +89,7 @@ public class AddressbookBean
 	{
 		long currentTime = System.currentTimeMillis();
 		
-		if( properties.size() > 0 &&  currentTime - configLastLoaded < 10000 )
+		if( !properties.isEmpty() &&  currentTime - configLastLoaded < 10000 )
 			return;
 		
 		FileInputStream fis = null;
diff --git a/apps/susidns/src/java/src/i2p/susi/dns/SubscriptionsBean.java b/apps/susidns/src/java/src/i2p/susi/dns/SubscriptionsBean.java
index cc983b54bf0c78ae105eae908304fb4abf54c047..6b1a80576999b83406f5de862d881755b6d3f92a 100644
--- a/apps/susidns/src/java/src/i2p/susi/dns/SubscriptionsBean.java
+++ b/apps/susidns/src/java/src/i2p/susi/dns/SubscriptionsBean.java
@@ -49,7 +49,7 @@ public class SubscriptionsBean
 	{
 		long currentTime = System.currentTimeMillis();
 		
-		if( properties.size() > 0 &&  currentTime - configLastLoaded < 10000 )
+		if( !properties.isEmpty() &&  currentTime - configLastLoaded < 10000 )
 			return;
 		
 		FileInputStream fis = null;
diff --git a/apps/susimail/src/src/i2p/susi/webmail/WebMail.java b/apps/susimail/src/src/i2p/susi/webmail/WebMail.java
index e871dfe817228e133c49af9ddcc350bac9252ee5..3771d02422523841624009a964e060929ebd090c 100644
--- a/apps/susimail/src/src/i2p/susi/webmail/WebMail.java
+++ b/apps/susimail/src/src/i2p/susi/webmail/WebMail.java
@@ -1411,7 +1411,7 @@ public class WebMail extends HttpServlet
 		if( bccToSelf != null && bccToSelf.compareTo( "1" ) == 0 )
 			recipients.add( sender );
 		
-		if( recipients.size() == 0 ) {
+		if( recipients.isEmpty() ) {
 			ok = false;
 			sessionObject.error += "No recipients found.<br>";
 		}
@@ -1442,7 +1442,7 @@ public class WebMail extends HttpServlet
 			}
 			String boundary = "_="+(int)(Math.random()*Integer.MAX_VALUE)+""+(int)(Math.random()*Integer.MAX_VALUE);
 			boolean multipart = false;
-			if( sessionObject.attachments != null && sessionObject.attachments.size() > 0 ) {
+			if( sessionObject.attachments != null && !sessionObject.attachments.isEmpty() ) {
 				multipart = true;
 				body.append( "\r\nMIME-Version: 1.0\r\nContent-type: multipart/mixed; boundary=\"" + boundary + "\"\r\n\r\n" );
 			}
@@ -1515,7 +1515,7 @@ public class WebMail extends HttpServlet
 	{
 		out.println( button( SEND, "Send" ) +
 				button( CANCEL, "Cancel" ) + spacer +
-				(sessionObject.attachments != null && sessionObject.attachments.size() > 0 ? button( DELETE_ATTACHMENT, "Delete Attachment" ) : button2( DELETE_ATTACHMENT, "Delete Attachment" ) ) + spacer +
+				(sessionObject.attachments != null && (!sessionObject.attachments.isEmpty()) ? button( DELETE_ATTACHMENT, "Delete Attachment" ) : button2( DELETE_ATTACHMENT, "Delete Attachment" ) ) + spacer +
 				button( RELOAD, "Reload Config" ) + spacer +
 				button( LOGOUT, "Logout" ) );
 
@@ -1550,7 +1550,7 @@ public class WebMail extends HttpServlet
 				"<tr><td colspan=\"2\" align=\"center\"><hr></td></tr>\n" +
 				"<tr><td align=\"right\">New Attachment:</td><td align=\"left\"><input type=\"file\" size=\"50%\" name=\"" + NEW_FILENAME + "\" value=\"\"><input type=\"submit\" name=\"" + NEW_UPLOAD + "\" value=\"Upload File\"></td></tr>" );
 		
-		if( sessionObject.attachments != null && sessionObject.attachments.size() > 0 ) {
+		if( sessionObject.attachments != null && !sessionObject.attachments.isEmpty() ) {
 			boolean wroteHeader = false;
 			for( Iterator it = sessionObject.attachments.iterator(); it.hasNext(); ) {
 				if( !wroteHeader ) {
diff --git a/build.xml b/build.xml
index b56d25cbb5f9a89691a9657fceed8708045d0374..5cfe3aa03416d8e34a1f0a12425a05a6989bd157 100644
--- a/build.xml
+++ b/build.xml
@@ -255,12 +255,12 @@
 	<defaultexcludes default="true"/>
     </target>
 
-    <!-- A few reeleases only, then back to updater. First release was 0.7.11 -->
+    <!-- A few reeleases only, then back to updater. Jetty fix for snark in 0.7.14 -->
     <target name="pkg" depends="distclean, updaterWithJettyFixes, preppkg, installer" />
 
     <target name="pkgclean" depends="deletepkg-temp">
         <delete>
-            <fileset dir="." includes="i2p.tar.bz2 install.jar i2pupdate.zip" />
+            <fileset dir="." includes="i2p.tar.bz2 install.jar i2pupdate.zip i2pupdate200.zip" />
         </delete>
     </target>
 
@@ -320,6 +320,10 @@
     </target>
 
     <target name="preppkg-base" depends="build, preplicenses, prepconsoleDocs">
+        <!-- if updater200 was run previously, it left *.pack files in pkg-temp -->
+        <delete>
+            <fileset dir="pkg-temp" includes="**/*.jar.pack **/*.war.pack" />
+        </delete>
         <copy file="build/i2p.jar" todir="pkg-temp/lib/" />
         <copy file="build/i2ptunnel.jar" todir="pkg-temp/lib/" />
         <copy file="build/jasper-compiler.jar" todir="pkg-temp/lib/" />
@@ -458,7 +462,8 @@
         <zip destfile="docs.zip" basedir="pkg-temp" whenempty="fail" />
     </target>
 
-    <target name="updater200" depends="prepupdate, preplicenses, pack200, zipit" />
+    <target name="updater200" depends="prepupdate, preplicenses, pack200, zipit200" />
+    <target name="updater200WithJettyFixes" depends="prepjupdatefixes, preplicenses, pack200, zipit200" />
     <target name="updater" depends="prepupdate, preplicenses, zipit" />
     <target name="updaterWithGeoIP" depends="prepupdate, prepgeoupdate, preplicenses, zipit" />
     <target name="updaterWithJetty" depends="prepjupdate, preplicenses, zipit" />
@@ -473,24 +478,27 @@
         <tar destfile="i2pupdate.tbz" basedir="pkg-temp" compression="bzip2" />
        -->
     </target>
+    <target name="zipit200">
+        <zip destfile="i2pupdate200.zip" basedir="pkg-temp" whenempty="fail" />
+    </target>
 
     <target name="pack200">
 <!-- *nix here -->
-        <exec executable="sh" osfamily="unix" failifexecutionfails="true">
+        <exec executable="sh" osfamily="unix" failonerror="true">
             <arg value="-c" />
             <arg value="for i in pkg-temp/lib/*.jar pkg-temp/webapps/*war; do echo pack200 $i; mv $i $i.jar; pack200 -g $i.pack $i.jar; rm -f $i.jar; done" />
         </exec>
-        <exec executable="sh" osfamily="mac" failifexecutionfails="true">
+        <exec executable="sh" osfamily="mac" failonerror="true">
             <arg value="-c" />
             <!-- pack200 will only pack to a .pack file, and only from a .jar file, so we put another .jar on the end -->
             <arg value="for i in pkg-temp/lib/*.jar pkg-temp/webapps/*war; do echo pack200 $i; mv $i $i.jar; pack200 -g $i.pack $i.jar; rm -f $i.jar; done" />
         </exec>
 <!-- windoz here : i admit, i hate escaped symbols in xml, indeed = =! -->
-		<exec executable="cmd" osfamily="windows" failifexecutionfails="true">
+		<exec executable="cmd" osfamily="windows" failonerror="true">
 			<arg value="/c" />
 			<arg value="for %i in (pkg-temp\webapps\*.war) do move %i %i.jar &amp;&amp; pack200 -g pkg-temp\webapps\%~ni.war.pack %i.jar &amp;&amp; del %i.jar" />
         </exec>
-		<exec executable="cmd" osfamily="windows" failifexecutionfails="true">
+		<exec executable="cmd" osfamily="windows" failonerror="true">
 			<arg value="/c" />
 			<arg value="for %i in (pkg-temp\lib\*.jar) do move %i %i.jar &amp;&amp; pack200 -g pkg-temp\lib\%~ni.jar.pack %i.jar &amp;&amp; del %i.jar" />
         </exec>
@@ -703,7 +711,10 @@
     <target name="distcleanWithDesktopgui" depends="distclean">
         <ant dir="apps/desktopgui" target="build_clean" />
     </target>
-    <target name="release" depends="pkg">
+
+    <!-- this is the same dependency as pkg, but with updater200 in the middle,
+         since preppkg puts too much stuff in pkg-temp -->
+    <target name="release" depends="distclean, updaterWithJettyFixes, updater200WithJettyFixes, preppkg, installer" >
         <echo message="================================================================" />
         <echo message="Did you update these files?" />
         <exec executable="ls" failonerror="true">
@@ -733,6 +744,7 @@
         <copy file="i2pupdate.zip" tofile="i2pupdate_${release.number}.zip" />
         <copy file="i2pinstall.exe" tofile="i2pinstall_${release.number}.exe" />
         <delete file="i2pupdate.sud" failonerror="false" />
+        <delete file="i2pupdate.su2" failonerror="false" />
         <input message="Enter private signing key file:" addproperty="release.privkey" />
         <fail message="You must enter a path." >
             <condition>
@@ -750,11 +762,6 @@
             <arg value="${release.privkey}" />
             <arg value="${release.number}" />
         </java>
-        <fail message="i2pupdate.sud generation failed!" >
-            <condition>
-                <length file="i2pupdate.sud" when="lt" length="1000000" />
-            </condition>
-        </fail>
         <echo message="Verify version and VALID signature:" />
         <java classname="net.i2p.crypto.TrustedUpdate" fork="true" failonerror="true">
             <classpath>
@@ -770,6 +777,32 @@
             <arg value="showversion" />
             <arg value="i2pupdate.sud" />
         </java>
+        <!-- now build and verify the packed sud from the packed zip -->
+        <java classname="net.i2p.crypto.TrustedUpdate" fork="true" failonerror="true">
+            <classpath>
+                <pathelement location="build/i2p.jar" />
+            </classpath>
+            <arg value="sign" />
+            <arg value="i2pupdate200.zip" />
+            <arg value="i2pupdate.su2" />
+            <arg value="${release.privkey}" />
+            <arg value="${release.number}" />
+        </java>
+        <echo message="Verify version and VALID signature:" />
+        <java classname="net.i2p.crypto.TrustedUpdate" fork="true" failonerror="true">
+            <classpath>
+                <pathelement location="build/i2p.jar" />
+            </classpath>
+            <arg value="verifysig" />
+            <arg value="i2pupdate.su2" />
+        </java>
+        <java classname="net.i2p.crypto.TrustedUpdate" fork="true" failonerror="true">
+            <classpath>
+                <pathelement location="build/i2p.jar" />
+            </classpath>
+            <arg value="showversion" />
+            <arg value="i2pupdate.su2" />
+        </java>
         <!-- will this use the monotonerc file in the current workspace? -->
         <echo message="Checking out fresh copy into ../i2p-${release.number} for tarballing:" />
         <delete dir="../i2p-${release.number}" />
@@ -813,6 +846,7 @@
             <arg value="i2pinstall_${release.number}.exe" />
             <arg value="i2psource_${release.number}.tar.bz2" />
             <arg value="i2pupdate_${release.number}.zip" />
+            <arg value="i2pupdate.su2" />
             <arg value="i2pupdate.sud" />
             <arg value="i2pinstall_${release.number}.exe.sig" />
             <arg value="i2psource_${release.number}.tar.bz2.sig" />
@@ -823,11 +857,13 @@
             <arg value="i2pinstall_${release.number}.exe" />
             <arg value="i2psource_${release.number}.tar.bz2" />
             <arg value="i2pupdate_${release.number}.zip" />
+            <arg value="i2pupdate.su2" />
             <arg value="i2pupdate.sud" />
         </exec>
         <echo message="Don't forget to mtn tag w: i2p-${release.number}" />
         <echo message="... and mtn cert t:i2p-${release.number} branch i2p.i2p.release" />
     </target>
+
     <target name="debian">
         <!-- binary only -->
         <echo message="Did you update the version in these files?" />
@@ -854,6 +890,7 @@
             <arg value="-I_MTN" />
         </exec>
     </target>
+
 <!-- the following are appened to help build barebone portable version, 
      none of the above is modified for this purpose -->
 	<target name = "pkg-portable-clean">
diff --git a/core/java/src/net/i2p/client/I2PSessionImpl.java b/core/java/src/net/i2p/client/I2PSessionImpl.java
index e4ee1c290dbab56980f6f9cb857d44c9b9086e9c..285aaa780bfd98c2dd369e13b2ee90ff999ece16 100644
--- a/core/java/src/net/i2p/client/I2PSessionImpl.java
+++ b/core/java/src/net/i2p/client/I2PSessionImpl.java
@@ -451,13 +451,13 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
                 Long msgId = null;
                 Integer size = null;
                 synchronized (AvailabilityNotifier.this) {
-                    if (_pendingIds.size() <= 0) {
+                    if (_pendingIds.isEmpty()) {
                         try {
                             AvailabilityNotifier.this.wait();
                         } catch (InterruptedException ie) { // nop
                         }
                     }
-                    if (_pendingIds.size() > 0) {
+                    if (!_pendingIds.isEmpty()) {
                         msgId = (Long)_pendingIds.remove(0);
                         size = (Integer)_pendingSizes.remove(0);
                     }
diff --git a/core/java/src/net/i2p/client/I2PSessionImpl2.java b/core/java/src/net/i2p/client/I2PSessionImpl2.java
index ac61ee703084e6504ba4982311c4c83181a34830..d8d8c8dfce202f8dd09c4dc37b1b4a6f42f0521d 100644
--- a/core/java/src/net/i2p/client/I2PSessionImpl2.java
+++ b/core/java/src/net/i2p/client/I2PSessionImpl2.java
@@ -236,7 +236,7 @@ class I2PSessionImpl2 extends I2PSessionImpl {
             oldTags = _context.sessionKeyManager().getAvailableTags(dest.getPublicKey(), key);
             long availTimeLeft = _context.sessionKeyManager().getAvailableTimeLeft(dest.getPublicKey(), key);
         
-            if ( (tagsSent == null) || (tagsSent.size() <= 0) ) {
+            if ( (tagsSent == null) || (tagsSent.isEmpty()) ) {
                 if (oldTags < NUM_TAGS) {
                     sentTags = createNewTags(NUM_TAGS);
                     if (_log.shouldLog(Log.DEBUG))
@@ -261,7 +261,7 @@ class I2PSessionImpl2 extends I2PSessionImpl {
             if (false) // rekey
                 newKey = _context.keyGenerator().generateSessionKey();
         
-            if ( (tagsSent != null) && (tagsSent.size() > 0) ) {
+            if ( (tagsSent != null) && (!tagsSent.isEmpty()) ) {
                 if (sentTags == null)
                     sentTags = new HashSet();
                 sentTags.addAll(tagsSent);
diff --git a/core/java/src/net/i2p/client/naming/EepGetNamingService.java b/core/java/src/net/i2p/client/naming/EepGetNamingService.java
index 8ddeaa2480d1cfce62274853ac0b52beb282e774..d8331796712770adeacfe73592675b7f85277f83 100644
--- a/core/java/src/net/i2p/client/naming/EepGetNamingService.java
+++ b/core/java/src/net/i2p/client/naming/EepGetNamingService.java
@@ -72,7 +72,7 @@ public class EepGetNamingService extends NamingService {
             return d;
 
         List URLs = getURLs();
-        if (URLs.size() == 0)
+        if (URLs.isEmpty())
             return null;
 
         // prevent lookup loops - this cannot be the only lookup service
diff --git a/core/java/src/net/i2p/crypto/CryptixAESKeyCache.java b/core/java/src/net/i2p/crypto/CryptixAESKeyCache.java
index 6231261d3b8a6f235b8070a68f3d32dd808fdf10..5084ae2b0a836d7d2c3e9416da754451e0fceacb 100644
--- a/core/java/src/net/i2p/crypto/CryptixAESKeyCache.java
+++ b/core/java/src/net/i2p/crypto/CryptixAESKeyCache.java
@@ -31,7 +31,7 @@ public final class CryptixAESKeyCache {
      */
     public final KeyCacheEntry acquireKey() {
         synchronized (_availableKeys) {
-            if (_availableKeys.size() > 0)
+            if (!_availableKeys.isEmpty())
                 return (KeyCacheEntry)_availableKeys.remove(0);
         }
         return createNew();
diff --git a/core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java b/core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java
index d51e2366c1998b8802889259c4c9e7a8b227cfd7..2c1e57d8e5795d52a3ddfe05de1085f89ff23b7a 100644
--- a/core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java
+++ b/core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java
@@ -114,7 +114,7 @@ public class DHSessionKeyBuilder {
         this(false);
         DHSessionKeyBuilder builder = null;
         synchronized (_builders) {
-            if (_builders.size() > 0) {
+            if (!_builders.isEmpty()) {
                 builder = (DHSessionKeyBuilder) _builders.remove(0);
                 if (_log.shouldLog(Log.DEBUG)) _log.debug("Removing a builder.  # left = " + _builders.size());
             } else {
diff --git a/core/java/src/net/i2p/crypto/ElGamalAESEngine.java b/core/java/src/net/i2p/crypto/ElGamalAESEngine.java
index 047b0156ef1159210f9495ef9661c6b7c3f07b90..820a57c672e7243476d1816f5f2e979703418e4c 100644
--- a/core/java/src/net/i2p/crypto/ElGamalAESEngine.java
+++ b/core/java/src/net/i2p/crypto/ElGamalAESEngine.java
@@ -104,7 +104,7 @@ public class ElGamalAESEngine {
             decrypted = decryptExistingSession(data, key, targetPrivateKey, foundTags, usedKey, foundKey);
             if (decrypted != null) {
                 _context.statManager().updateFrequency("crypto.elGamalAES.decryptExistingSession");
-                if ( (foundTags.size() > 0) && (_log.shouldLog(Log.DEBUG)) )
+                if ( (!foundTags.isEmpty()) && (_log.shouldLog(Log.DEBUG)) )
                     _log.debug(id + ": ElG/AES decrypt success with " + st + ": found tags: " + foundTags);
                 wasExisting = true;
             } else {
@@ -118,7 +118,7 @@ public class ElGamalAESEngine {
             decrypted = decryptNewSession(data, targetPrivateKey, foundTags, usedKey, foundKey);
             if (decrypted != null) {
                 _context.statManager().updateFrequency("crypto.elGamalAES.decryptNewSession");
-                if ( (foundTags.size() > 0) && (_log.shouldLog(Log.DEBUG)) )
+                if ( (!foundTags.isEmpty()) && (_log.shouldLog(Log.DEBUG)) )
                     _log.debug("ElG decrypt success: found tags: " + foundTags);
             } else {
                 _context.statManager().updateFrequency("crypto.elGamalAES.decryptFailed");
@@ -131,7 +131,7 @@ public class ElGamalAESEngine {
             //_log.debug("Unable to decrypt the data starting with tag [" + st + "] - did the tag expire recently?", new Exception("Decrypt failure"));
         }
 
-        if (foundTags.size() > 0) {
+        if (!foundTags.isEmpty()) {
             if (foundKey.getData() != null) {
                 if (_log.shouldLog(Log.DEBUG)) 
                     _log.debug("Found key: " + foundKey.toBase64() + " tags: " + foundTags + " wasExisting? " + wasExisting);
diff --git a/core/java/src/net/i2p/crypto/HMAC256Generator.java b/core/java/src/net/i2p/crypto/HMAC256Generator.java
index e84489d97173337d30dcdf92a26c85ac23c47067..bf053210942f9e29025fd28889d13d01fcff16aa 100644
--- a/core/java/src/net/i2p/crypto/HMAC256Generator.java
+++ b/core/java/src/net/i2p/crypto/HMAC256Generator.java
@@ -22,7 +22,7 @@ public class HMAC256Generator extends HMACGenerator {
     @Override
     protected I2PHMac acquire() {
         synchronized (_available) {
-            if (_available.size() > 0)
+            if (!_available.isEmpty())
                 return (I2PHMac)_available.remove(0);
         }
         // the HMAC is hardcoded to use SHA256 digest size
diff --git a/core/java/src/net/i2p/crypto/HMACGenerator.java b/core/java/src/net/i2p/crypto/HMACGenerator.java
index 9bf06aa70e32f83391daa70aa755b57e55928bcf..aed444ed06118259ac253745cdc4d715510e0ed5 100644
--- a/core/java/src/net/i2p/crypto/HMACGenerator.java
+++ b/core/java/src/net/i2p/crypto/HMACGenerator.java
@@ -89,7 +89,7 @@ public class HMACGenerator {
     
     protected I2PHMac acquire() {
         synchronized (_available) {
-            if (_available.size() > 0)
+            if (!_available.isEmpty())
                 return (I2PHMac)_available.remove(0);
         }
         // the HMAC is hardcoded to use SHA256 digest size
@@ -108,7 +108,7 @@ public class HMACGenerator {
     private byte[] acquireTmp() {
         byte rv[] = null;
         synchronized (_availableTmp) {
-            if (_availableTmp.size() > 0)
+            if (!_availableTmp.isEmpty())
                 rv = (byte[])_availableTmp.remove(0);
         }
         if (rv != null)
diff --git a/core/java/src/net/i2p/crypto/SHA256Generator.java b/core/java/src/net/i2p/crypto/SHA256Generator.java
index e34f4fe914fe49e8e408cf317e16c9dd2aaeb1ed..d24915ed54da17088281d08d67dd75447128d5ea 100644
--- a/core/java/src/net/i2p/crypto/SHA256Generator.java
+++ b/core/java/src/net/i2p/crypto/SHA256Generator.java
@@ -52,7 +52,7 @@ public final class SHA256Generator {
     private Sha256Standalone acquireGnu() {
         Sha256Standalone rv = null;
         synchronized (_digestsGnu) {
-            if (_digestsGnu.size() > 0)
+            if (!_digestsGnu.isEmpty())
                 rv = (Sha256Standalone)_digestsGnu.remove(0);
         }
         if (rv != null)
diff --git a/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java b/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java
index 17543b1bd8cd7c0b305f3dd2ffb32d4e1cfcaf02..bd68f1f54b6bdb78fc295a3d8da2a2dfc453fe9a 100644
--- a/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java
+++ b/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java
@@ -307,7 +307,7 @@ public class TransientSessionKeyManager extends SessionKeyManager {
     public TagSetHandle tagsDelivered(PublicKey target, SessionKey key, Set<SessionTag> sessionTags) {
         if (_log.shouldLog(Log.DEBUG)) {
             //_log.debug("Tags delivered to set " + set + " on session " + sess);
-            if (sessionTags.size() > 0)
+            if (!sessionTags.isEmpty())
                 _log.debug("Tags delivered: " + sessionTags.size() + " for key: " + key + ": " + sessionTags);
         }
         OutboundSession sess = getSession(target);
@@ -415,7 +415,7 @@ public class TransientSessionKeyManager extends SessionKeyManager {
         if (overage > 0)
             clearExcess(overage);
 
-        if ( (sessionTags.size() <= 0) && (_log.shouldLog(Log.DEBUG)) )
+        if ( (sessionTags.isEmpty()) && (_log.shouldLog(Log.DEBUG)) )
             _log.debug("Received 0 tags for key " + key);
         //if (false) aggressiveExpire();
     }
@@ -785,7 +785,7 @@ public class TransientSessionKeyManager extends SessionKeyManager {
             long now = _context.clock().now();
             _lastUsed = now;
             synchronized (_tagSets) {
-                while (_tagSets.size() > 0) {
+                while (!_tagSets.isEmpty()) {
                     TagSet set = _tagSets.get(0);
                     if (set.getDate() + SESSION_TAG_DURATION_MS > now) {
                         SessionTag tag = set.consumeNext();
@@ -830,7 +830,7 @@ public class TransientSessionKeyManager extends SessionKeyManager {
             synchronized (_tagSets) {
                 for (Iterator<TagSet> iter = _tagSets.iterator(); iter.hasNext();) {
                     TagSet set = iter.next();
-                    if ( (set.getDate() > last) && (set.getTags().size() > 0) ) 
+                    if ( (set.getDate() > last) && (!set.getTags().isEmpty()) ) 
                         last = set.getDate();
                 }
             }
diff --git a/core/java/src/net/i2p/crypto/YKGenerator.java b/core/java/src/net/i2p/crypto/YKGenerator.java
index cc69fb5d8fedaed8dc488c6269da5f3c6164649b..ad68ebec1fd56a2c2e78c6c18b383f9deadb89c4 100644
--- a/core/java/src/net/i2p/crypto/YKGenerator.java
+++ b/core/java/src/net/i2p/crypto/YKGenerator.java
@@ -110,7 +110,7 @@ class YKGenerator {
     public static BigInteger[] getNextYK() {
         if (true) {
             synchronized (_values) {
-                if (_values.size() > 0) {
+                if (!_values.isEmpty()) {
                     if (_log.shouldLog(Log.DEBUG))
                         _log.debug("Sufficient precalculated YK values - fetch the existing");
                     return (BigInteger[]) _values.remove(0);
diff --git a/core/java/src/net/i2p/data/DataHelper.java b/core/java/src/net/i2p/data/DataHelper.java
index dfbb5c718a557eb86fc2e0d27a2e061428b84bcd..39771212e45e816fc05a14bc027f09fd330763f5 100644
--- a/core/java/src/net/i2p/data/DataHelper.java
+++ b/core/java/src/net/i2p/data/DataHelper.java
@@ -30,6 +30,7 @@ import java.text.DecimalFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
@@ -965,16 +966,22 @@ public class DataHelper {
         out.write(data);
     }
 
-    public static List sortStructures(Collection dataStructures) {
-        if (dataStructures == null) return new ArrayList();
-        ArrayList rv = new ArrayList(dataStructures.size());
-        TreeMap tm = new TreeMap();
-        for (Iterator iter = dataStructures.iterator(); iter.hasNext();) {
-            DataStructure struct = (DataStructure) iter.next();
+    /**
+     *  Sort based on the Hash of the DataStructure
+     *  Warning - relatively slow.
+     *  Only used by RouterInfo
+     *  Why? Just because it has to be consistent so signing will work?
+     *  How to spec as returning the same type as the param?
+     */
+    public static List<? extends DataStructure> sortStructures(Collection<? extends DataStructure> dataStructures) {
+        if (dataStructures == null) return Collections.EMPTY_LIST;
+        ArrayList<DataStructure> rv = new ArrayList(dataStructures.size());
+        TreeMap<String, DataStructure> tm = new TreeMap();
+        for (DataStructure struct : dataStructures) {
             tm.put(struct.calculateHash().toString(), struct);
         }
-        for (Iterator iter = tm.values().iterator(); iter.hasNext();) {
-            rv.add(iter.next());
+        for (DataStructure struct : tm.values()) {
+            rv.add(struct);
         }
         return rv;
     }
diff --git a/core/java/src/net/i2p/data/LeaseSet.java b/core/java/src/net/i2p/data/LeaseSet.java
index 4598a27ff9059b2f6105fc43951c604e0edc4b79..a917f6ac0536e8656c8f5b1ffeded5e899c20c6b 100644
--- a/core/java/src/net/i2p/data/LeaseSet.java
+++ b/core/java/src/net/i2p/data/LeaseSet.java
@@ -201,7 +201,7 @@ public class LeaseSet extends DataStructureImpl {
      * @return earliest end date of any lease in the set, or -1 if there are no leases
      */
     public long getEarliestLeaseDate() {
-        if (_leases.size() <= 0)
+        if (_leases.isEmpty())
             return -1;
         return _firstExpiration;
     }
diff --git a/core/java/src/net/i2p/data/RouterInfo.java b/core/java/src/net/i2p/data/RouterInfo.java
index 3f4caa71170f241bc37d6ae0ee25e9eca7be4017..20de623e8b3d453ff8dc08b8b2453833787f3170 100644
--- a/core/java/src/net/i2p/data/RouterInfo.java
+++ b/core/java/src/net/i2p/data/RouterInfo.java
@@ -13,6 +13,7 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Collection;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -264,14 +265,16 @@ public class RouterInfo extends DataStructureImpl {
         try {
             _identity.writeBytes(out);
             DataHelper.writeDate(out, new Date(_published));
-            if (isHidden()) {
+            int sz = _addresses.size();
+            if (sz <= 0 || isHidden()) {
                 // Do not send IP address to peers in hidden mode
                 DataHelper.writeLong(out, 1, 0);
             } else {
-                DataHelper.writeLong(out, 1, _addresses.size());
-                List addresses = DataHelper.sortStructures(_addresses);
-                for (Iterator iter = addresses.iterator(); iter.hasNext();) {
-                    RouterAddress addr = (RouterAddress) iter.next();
+                DataHelper.writeLong(out, 1, sz);
+                Collection<RouterAddress> addresses = _addresses;
+                if (sz > 1)
+                    addresses = (Collection<RouterAddress>) DataHelper.sortStructures(addresses);
+                for (RouterAddress addr : addresses) {
                     addr.writeBytes(out);
                 }
             }
@@ -279,12 +282,16 @@ public class RouterInfo extends DataStructureImpl {
             // answer: they're always empty... they're a placeholder for one particular
             //         method of trusted links, which isn't implemented in the router
             //         at the moment, and may not be later.
-            // fixme to reduce objects - if (_peers == null) write 0
-            DataHelper.writeLong(out, 1, _peers.size());
-            List peers = DataHelper.sortStructures(_peers);
-            for (Iterator iter = peers.iterator(); iter.hasNext();) {
-                Hash peerHash = (Hash) iter.next();
-                peerHash.writeBytes(out);
+            // fixme to reduce objects - allow _peers == null
+            int psz = _peers.size();
+            DataHelper.writeLong(out, 1, psz);
+            if (psz > 0) {
+                Collection<Hash> peers = _peers;
+                if (psz > 1)
+                    peers = (Collection<Hash>) DataHelper.sortStructures(peers);
+                for (Hash peerHash : peers) {
+                    peerHash.writeBytes(out);
+                }
             }
             DataHelper.writeProperties(out, _options);
         } catch (IOException ioe) {
diff --git a/core/java/src/net/i2p/stat/BufferedStatLog.java b/core/java/src/net/i2p/stat/BufferedStatLog.java
index 4703a257605103b26aa756b73eb62a36a0d9a661..fc7b85c3f55bcb6b02ef6e2f43c540c588c79fbc 100644
--- a/core/java/src/net/i2p/stat/BufferedStatLog.java
+++ b/core/java/src/net/i2p/stat/BufferedStatLog.java
@@ -94,7 +94,7 @@ public class BufferedStatLog implements StatLog {
                     _statFilters.clear();
                     while (tok.hasMoreTokens())
                         _statFilters.add(tok.nextToken().trim());
-                    _filtersSpecified = _statFilters.size() > 0;
+                    _filtersSpecified = !_statFilters.isEmpty();
                 }
             }
             _lastFilters = val;
diff --git a/core/java/src/net/i2p/util/EepGet.java b/core/java/src/net/i2p/util/EepGet.java
index 70913615cf459859473bbc7da58f8466cf8f16f3..3fec768a5857cf153a9bc7d0606019ffcd56d54a 100644
--- a/core/java/src/net/i2p/util/EepGet.java
+++ b/core/java/src/net/i2p/util/EepGet.java
@@ -72,6 +72,8 @@ public class EepGet {
     protected static final String USER_AGENT = "Wget/1.11.4";
     protected static final long CONNECT_TIMEOUT = 45*1000;
     protected static final long INACTIVITY_TIMEOUT = 60*1000;
+    /** maximum times to try without getting any data at all, even if numRetries is higher @since 0.7.14 */
+    protected static final int MAX_COMPLETE_FAILS = 5;
     
     public EepGet(I2PAppContext ctx, String proxyHost, int proxyPort, int numRetries, String outputFile, String url) {
         this(ctx, true, proxyHost, proxyPort, numRetries, outputFile, url);
@@ -473,7 +475,9 @@ public class EepGet {
             }
 
             _currentAttempt++;
-            if (_currentAttempt > _numRetries || !_keepFetching) 
+            if (_currentAttempt > _numRetries ||
+                (_alreadyTransferred == 0 && _currentAttempt > MAX_COMPLETE_FAILS) ||
+                !_keepFetching) 
                 break;
             try { 
                 long delay = _context.random().nextInt(60*1000);
diff --git a/core/java/src/net/i2p/util/Executor.java b/core/java/src/net/i2p/util/Executor.java
index 5fa26ec744078922511bb0422771366632a87e99..8092d7ac447ee98f152306101d59e925fb18baf6 100644
--- a/core/java/src/net/i2p/util/Executor.java
+++ b/core/java/src/net/i2p/util/Executor.java
@@ -20,9 +20,9 @@ class Executor implements Runnable {
         while(runn.getAnswer()) {
             SimpleTimer.TimedEvent evt = null;
             synchronized (_readyEvents) {
-                if (_readyEvents.size() <= 0) 
+                if (_readyEvents.isEmpty()) 
                     try { _readyEvents.wait(); } catch (InterruptedException ie) {}
-                if (_readyEvents.size() > 0) 
+                if (!_readyEvents.isEmpty()) 
                     evt = (SimpleTimer.TimedEvent)_readyEvents.remove(0);
             }
 
diff --git a/core/java/src/net/i2p/util/SimpleTimer.java b/core/java/src/net/i2p/util/SimpleTimer.java
index cf8e7e34b4a6ab31e7b5a3c4fe2f4eb453345509..6a8b855e305f3cfc892c78c4306de871c1346e73 100644
--- a/core/java/src/net/i2p/util/SimpleTimer.java
+++ b/core/java/src/net/i2p/util/SimpleTimer.java
@@ -180,7 +180,7 @@ public class SimpleTimer {
                         long nextEventDelay = -1;
                         Object nextEvent = null;
                         while(runn.getAnswer()) {
-                            if(_events.size() <= 0) {
+                            if(_events.isEmpty()) {
                                 break;
                             }
                             Long when = (Long)_events.firstKey();
@@ -196,7 +196,7 @@ public class SimpleTimer {
                                 break;
                             }
                         }
-                        if (eventsToFire.size() <= 0) { 
+                        if (eventsToFire.isEmpty()) { 
                             if (nextEventDelay != -1) {
                                 if (_log.shouldLog(Log.DEBUG))
                                     _log.debug("Next event in " + nextEventDelay + ": " + nextEvent);
diff --git a/core/java/src/org/bouncycastle/crypto/macs/I2PHMac.java b/core/java/src/org/bouncycastle/crypto/macs/I2PHMac.java
index a566e8a79936b52bfe131e9d55478d15f5465d32..125583613589391c50b042b8fc489d5762f9a790 100644
--- a/core/java/src/org/bouncycastle/crypto/macs/I2PHMac.java
+++ b/core/java/src/org/bouncycastle/crypto/macs/I2PHMac.java
@@ -172,7 +172,7 @@ implements Mac
     private static byte[] acquireTmp(int sz) {
         byte rv[] = null;
         synchronized (_tmpBuf[sz == 32 ? 0 : 1]) {
-            if (_tmpBuf[sz == 32 ? 0 : 1].size() > 0)
+            if (!_tmpBuf[sz == 32 ? 0 : 1].isEmpty())
                 rv = (byte[])_tmpBuf[sz == 32 ? 0 : 1].remove(0);
         }
         if (rv != null)
diff --git a/history.txt b/history.txt
index 8f29bb18c2f2a9e95cdeb8743b22094e82e938d8..15fca9fff42345d91f225f41a5ffc100c7e289cd 100644
--- a/history.txt
+++ b/history.txt
@@ -1,3 +1,17 @@
+2010-05-05 zzz
+    * build.xml: Create packed sud in release
+    * Console:
+      - Print stack trace if exception on startup
+      - IllegalStateException rather than NPE if no context
+    * EepGet: Limit max times to fail completely even if numRetries is higher
+    * i2psnark: Skip 'the' when sorting snarks
+    * I2PTunnelHTTPClient: Reject 192.168.*
+    * Plugins:
+      - Set classpath for specific client only, not for the whole JVM
+      - Use ConfigDir() not AppDir()
+    * Replace size() <= 0 with isEmpty() everywhere, ditto > 0 -> !isEmpty()
+    * RouterInfo: Clean up use of sortStructures()
+
 2010-05-02 zzz
     * ByteCache:
       - Add a per-cache stat
diff --git a/installer/resources/proxy/localhost-header.ht b/installer/resources/proxy/localhost-header.ht
index cbb2715cb6ca29effdda10fe0c933ce18ec233a4..82af7130b6dbbd49d40526b9c9a6e9cb8103a1da 100644
--- a/installer/resources/proxy/localhost-header.ht
+++ b/installer/resources/proxy/localhost-header.ht
@@ -5,7 +5,7 @@ Connection: close
 Proxy-Connection: close
 
 <html><head>
-<title>I2P Warning: Request Denied</title>
+<title>I2P Error: Request Denied</title>
 <link rel="shortcut icon" href="http://proxy.i2p/themes/console/images/favicon.ico" >
 <link href="http://proxy.i2p/themes/console/default/console.css" rel="stylesheet" type="text/css" >
 </head>
@@ -18,6 +18,7 @@ Proxy-Connection: close
 </div>
 ------------------------------>
 <div class=warning id=warning>
-<h3>Warning: Localhost Access</h3>
-Your browser is misconfigured. Do not use the proxy to access the router console or other localhost destinations.
+<h3>Error: Local Access</h3>
+Your browser is misconfigured. Do not use the proxy to access the router console,
+localhost, or local LAN destinations.
 </div>
diff --git a/router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java b/router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java
index 3b197ee927e04cf8f4cb0dc7224683722848eb87..80aaa889182b5924add0ad029234814e1c0ba259 100644
--- a/router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java
+++ b/router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java
@@ -205,7 +205,7 @@ public class DatabaseLookupMessage extends I2NPMessageImpl {
         } else {
             out[curIndex++] = DataHelper.BOOLEAN_FALSE;
         }
-        if ( (_dontIncludePeers == null) || (_dontIncludePeers.size() <= 0) ) {
+        if ( (_dontIncludePeers == null) || (_dontIncludePeers.isEmpty()) ) {
             out[curIndex++] = 0x0;
             out[curIndex++] = 0x0;
         } else {
diff --git a/router/java/src/net/i2p/router/Blocklist.java b/router/java/src/net/i2p/router/Blocklist.java
index 4f14fe8bb1e6fc898d5a0eb6118eda0bde1e3235..0f68355db2a392eba7abc8f9cafd9d7147fae395 100644
--- a/router/java/src/net/i2p/router/Blocklist.java
+++ b/router/java/src/net/i2p/router/Blocklist.java
@@ -472,7 +472,7 @@ public class Blocklist {
         RouterInfo pinfo = _context.netDb().lookupRouterInfoLocally(peer);
         if (pinfo == null) return rv;
         Set<RouterAddress> paddr = pinfo.getAddresses();
-        if (paddr == null || paddr.size() == 0)
+        if (paddr == null || paddr.isEmpty())
             return rv;
         String oldphost = null;
         List<RouterAddress> pladdr = new ArrayList(paddr);
@@ -773,7 +773,7 @@ public class Blocklist {
         //out.write("<h2>Banned IPs</h2>");
         Set<Integer> singles = new TreeSet();
         singles.addAll(_singleIPBlocklist);
-        if (singles.size() > 0) {
+        if (!singles.isEmpty()) {
             out.write("<table><tr><td><b>Transient IPs</b></td></tr>");
             for (Iterator<Integer> iter = singles.iterator(); iter.hasNext(); ) {
                  int ip = iter.next().intValue();
diff --git a/router/java/src/net/i2p/router/InNetMessagePool.java b/router/java/src/net/i2p/router/InNetMessagePool.java
index d7b3b9222462e8cf0b45ae62c6554b1ebd09ae69..47b799da5cc09c1d5a93836f866cc20eaeb2ff37 100644
--- a/router/java/src/net/i2p/router/InNetMessagePool.java
+++ b/router/java/src/net/i2p/router/InNetMessagePool.java
@@ -356,7 +356,7 @@ public class InNetMessagePool implements Service {
             I2NPMessage msg = null;
             Hash from = null;
             synchronized (_pendingDataMessages) {
-                if (_pendingDataMessages.size() > 0) {
+                if (!_pendingDataMessages.isEmpty()) {
                     msg = (I2NPMessage)_pendingDataMessages.remove(0);
                     from = (Hash)_pendingDataMessagesFrom.remove(0);
                 }
@@ -379,7 +379,7 @@ public class InNetMessagePool implements Service {
             I2NPMessage msg = null;
             int remaining = 0;
             synchronized (_pendingGatewayMessages) {
-                if (_pendingGatewayMessages.size() > 0)
+                if (!_pendingGatewayMessages.isEmpty())
                     msg = (I2NPMessage)_pendingGatewayMessages.remove(0);
                 remaining = _pendingGatewayMessages.size();
             }
@@ -397,7 +397,7 @@ public class InNetMessagePool implements Service {
                 I2NPMessage msg = null;
                 try {
                     synchronized (_pendingGatewayMessages) {
-                        if (_pendingGatewayMessages.size() <= 0)
+                        if (_pendingGatewayMessages.isEmpty())
                             _pendingGatewayMessages.wait();
                         else
                             msg = (I2NPMessage)_pendingGatewayMessages.remove(0);
@@ -428,7 +428,7 @@ public class InNetMessagePool implements Service {
                 Hash from = null;
                 try {
                     synchronized (_pendingDataMessages) {
-                        if (_pendingDataMessages.size() <= 0) {
+                        if (_pendingDataMessages.isEmpty()) {
                             _pendingDataMessages.wait();
                         } else {
                             msg = (I2NPMessage)_pendingDataMessages.remove(0);
diff --git a/router/java/src/net/i2p/router/JobQueue.java b/router/java/src/net/i2p/router/JobQueue.java
index facdb8921ce89a9255898decb153e0d44fc42642..892a678edc094837c560de06d2a7b573a3933484 100644
--- a/router/java/src/net/i2p/router/JobQueue.java
+++ b/router/java/src/net/i2p/router/JobQueue.java
@@ -383,7 +383,7 @@ public class JobQueue {
     public synchronized void runQueue(int numThreads) {
             // we're still starting up [serially] and we've got at least one runner,
             // so dont do anything
-            if ( (_queueRunners.size() > 0) && (!_allowParallelOperation) ) return;
+            if ( (!_queueRunners.isEmpty()) && (!_allowParallelOperation) ) return;
 
             // we've already enabled parallel operation, so grow to however many are
             // specified
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index 282c18b42238909e2faa8bba95d82c15667d116c..0725033fa600cfb5180ac82283f5194ee35b34b0 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -18,7 +18,7 @@ public class RouterVersion {
     /** deprecated */
     public final static String ID = "Monotone";
     public final static String VERSION = CoreVersion.VERSION;
-    public final static long BUILD = 2;
+    public final static long BUILD = 3;
 
     /** for example "-test" */
     public final static String EXTRA = "";
diff --git a/router/java/src/net/i2p/router/Shitlist.java b/router/java/src/net/i2p/router/Shitlist.java
index 482d4264c0e0a88b6b2e0e37a096e72ba0ef229f..f675d1056578151db6f8c55a560de209d1d9b793 100644
--- a/router/java/src/net/i2p/router/Shitlist.java
+++ b/router/java/src/net/i2p/router/Shitlist.java
@@ -210,7 +210,7 @@ public class Shitlist {
             fully = true;
         } else {
             e.transports.remove(transport);
-            if (e.transports.size() <= 0)
+            if (e.transports.isEmpty())
                 fully = true;
             else
                 _entries.put(peer, e);
diff --git a/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java b/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java
index 770c228222dac4dae1dda19a708dd8567c7e87d3..45622d117016a84e44b0a3675b9744061bdc149f 100644
--- a/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java
+++ b/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java
@@ -363,7 +363,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
             }
         }
         
-        if (leases.size() <= 0) {
+        if (leases.isEmpty()) {
             if (_log.shouldLog(Log.INFO))
                 _log.info(getJobId() + ": No leases found from: " + _leaseSet);
             return false;
@@ -536,7 +536,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
         ReplySelector selector = null;
         if (wantACK) {
             TagSetHandle tsh = null;
-            if ( (sessKey != null) && (tags != null) && (tags.size() > 0) ) {
+            if ( (sessKey != null) && (tags != null) && (!tags.isEmpty()) ) {
                 if (_leaseSet != null) {
                     SessionKeyManager skm = getContext().clientManager().getClientSessionKeyManager(_from.calculateHash());
                     if (skm != null)
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlySearchJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlySearchJob.java
index 1b81b6e37d479a2c3f9ae1f1198c0e5cc0c39c32..9f21962c197aaf84009640c2489e2d2c195f9597 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlySearchJob.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlySearchJob.java
@@ -93,13 +93,13 @@ class FloodOnlySearchJob extends FloodSearchJob {
         _shouldProcessDSRM = floodfillPeers.size() < MIN_FOR_NO_DSRM ||
                              getContext().routingKeyGenerator().getLastChanged() > getContext().clock().now() - 30*60*1000;
 
-        if (floodfillPeers.size() <= 0) {
+        if (floodfillPeers.isEmpty()) {
             // ask anybody, they may not return the answer but they will return a few ff peers we can go look up,
             // so this situation should be temporary
             if (_log.shouldLog(Log.WARN))
                 _log.warn("Running netDb searches against the floodfill peers, but we don't know any");
             floodfillPeers = new ArrayList(_facade.getAllRouters());
-            if (floodfillPeers.size() <= 0) {
+            if (floodfillPeers.isEmpty()) {
                 if (_log.shouldLog(Log.ERROR))
                     _log.error("We don't know any peers at all");
                 failed();
@@ -256,7 +256,7 @@ class FloodOnlySearchJob extends FloodSearchJob {
         _facade.complete(_key);
         getContext().statManager().addRateData("netDb.successTime", System.currentTimeMillis()-_created, System.currentTimeMillis()-_created);
         synchronized (_onFind) {
-            while (_onFind.size() > 0)
+            while (!_onFind.isEmpty())
                 getContext().jobQueue().addJob((Job)_onFind.remove(0));
         }
     }
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodSearchJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodSearchJob.java
index 09f593c80a39308f0c9f0b65f2f8116e820dc128..bfa5c59ead02121e2f0a5c49870140b6ae7c6a58 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodSearchJob.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodSearchJob.java
@@ -96,7 +96,7 @@ public class FloodSearchJob extends JobImpl {
                     removed = new ArrayList(_onFailed);
                     _onFailed.clear();
                 }
-                while (removed.size() > 0)
+                while (!removed.isEmpty())
                     getContext().jobQueue().addJob(removed.remove(0));
                 getContext().messageRegistry().unregisterPending(out);
                 return;
@@ -140,7 +140,7 @@ public class FloodSearchJob extends JobImpl {
                 removed = new ArrayList(_onFailed);
                 _onFailed.clear();
             }
-            while (removed.size() > 0)
+            while (!removed.isEmpty())
                 getContext().jobQueue().addJob(removed.remove(0));
         }
     }
@@ -155,7 +155,7 @@ public class FloodSearchJob extends JobImpl {
             removed = new ArrayList(_onFind);
             _onFind.clear();
         }
-        while (removed.size() > 0)
+        while (!removed.isEmpty())
             getContext().jobQueue().addJob(removed.remove(0));
     }
 
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillMonitorJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillMonitorJob.java
index 291080f39f7d5519837df3d6cee30d5082949961..3964b3a1ea49246f856362ed52a7c05662335e39 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillMonitorJob.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillMonitorJob.java
@@ -83,7 +83,7 @@ class FloodfillMonitorJob extends JobImpl {
         List floodfillPeers = _facade.getFloodfillPeers();
         long now = getContext().clock().now();
         // We know none at all! Must be our turn...
-        if (floodfillPeers == null || floodfillPeers.size() <= 0) {
+        if (floodfillPeers == null || floodfillPeers.isEmpty()) {
             _lastChanged = now;
             return true;
         }
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java
index 61cc5f1aa4031cef47a5ba8815d52ebd82b14386..540173ed63404457315894cf71bd784db7bc8788 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java
@@ -305,13 +305,13 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad
         Job fail = null;
         if (onFind != null) {
             synchronized (onFind) {
-                if (onFind.size() > 0)
+                if (!onFind.isEmpty())
                     find = onFind.remove(0);
             } 
         }
         if (onFailed != null) {
             synchronized (onFailed) {
-                if (onFailed.size() > 0)
+                if (!onFailed.isEmpty())
                     fail = onFailed.remove(0);
             }
         }
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java
index 9cacb0eed437c3da0621160adfd3579d3f4324c0..c4e1140c2a872cf38db4a03ff61f8e69024192a5 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java
@@ -313,7 +313,7 @@ class FloodfillPeerSelector extends PeerSelector {
             }
             // are we corrupting _sorted here?
             for (int i = rv.size(); i < howMany; i++) {
-                if (_sorted.size() <= 0)
+                if (_sorted.isEmpty())
                     break;
                 Hash entry = _sorted.first();
                 rv.add(entry);
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillVerifyStoreJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillVerifyStoreJob.java
index 5dd5a261bf0367c25248ce29ba47e9352a7b9afc..fa944f384dafc0c53a653f3b593532597ac692bb 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillVerifyStoreJob.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillVerifyStoreJob.java
@@ -138,7 +138,7 @@ public class FloodfillVerifyStoreJob extends JobImpl {
         Hash rkey = getContext().routingKeyGenerator().getRoutingKey(_key);
         FloodfillPeerSelector sel = (FloodfillPeerSelector)_facade.getPeerSelector();
         List<Hash> peers = sel.selectFloodfillParticipants(rkey, 1, _ignore, _facade.getKBuckets());
-        if (peers.size() > 0)
+        if (!peers.isEmpty())
             return peers.get(0);
         
         if (_log.shouldLog(Log.WARN))
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java
index 9b01d6404d38e13afa0e33d8948604c9786588f3..d978f8488f43e246c0d08e5189b98be2652c5213 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java
@@ -725,7 +725,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
             long age = _context.clock().now() - routerInfo.getPublished();
             return "Peer " + key.toBase64() + " published " + DataHelper.formatDuration(age) + " ago";
         } else if (upLongEnough && !routerInfo.isCurrent(ROUTER_INFO_EXPIRATION_SHORT)) {
-            if (routerInfo.getAddresses().size() <= 0)
+            if (routerInfo.getAddresses().isEmpty())
                 return "Peer " + key.toBase64() + " published > 90m ago with no addresses";
             RouterAddress ra = routerInfo.getTargetAddress("SSU");
             if (ra != null) {
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/MessageWrapper.java b/router/java/src/net/i2p/router/networkdb/kademlia/MessageWrapper.java
index 73ed7ad70477d714a12853705fff026e4fc5539a..82c7f121f02e3ca7f46c671d71e09ca5a1a9d613 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/MessageWrapper.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/MessageWrapper.java
@@ -69,7 +69,7 @@ class MessageWrapper {
             return null;
         TagSetHandle tsh = null;
         PublicKey sentTo = to.getIdentity().getPublicKey();
-        if (sentTags.size() > 0)
+        if (!sentTags.isEmpty())
             tsh = skm.tagsDelivered(sentTo, sentKey, sentTags);
         if (_log.shouldLog(Log.DEBUG))
             _log.debug("Sent to: " + to.getIdentity().getHash() + " with key: " + sentKey + " and tags: " + sentTags.size());
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/PeerSelector.java b/router/java/src/net/i2p/router/networkdb/kademlia/PeerSelector.java
index 7ce9853caa59f0f43385b817923d5349a44c3581..17441420262f10a03726dda007b98a522b5e1af1 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/PeerSelector.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/PeerSelector.java
@@ -140,7 +140,7 @@ public class PeerSelector {
         public List<Hash> get(int howMany) {
             List<Hash> rv = new ArrayList(howMany);
             for (int i = 0; i < howMany; i++) {
-                if (_sorted.size() <= 0)
+                if (_sorted.isEmpty())
                     break;
                 rv.add(_sorted.remove(_sorted.firstKey()));
             }
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/SearchJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/SearchJob.java
index fe3c7548510d97b71c6e4f01b1dfbc14a14d4168..9400a17f696394d1d2be36ce0a432afc00c5f1cc 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/SearchJob.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/SearchJob.java
@@ -265,7 +265,7 @@ class SearchJob extends JobImpl {
         while (sent <= 0) {
             //boolean onlyFloodfill = onlyQueryFloodfillPeers(getContext());
             boolean onlyFloodfill = true;
-            if (_floodfillPeersExhausted && onlyFloodfill && _state.getPending().size() <= 0) {
+            if (_floodfillPeersExhausted && onlyFloodfill && _state.getPending().isEmpty()) {
                 if (_log.shouldLog(Log.WARN))
                     _log.warn(getJobId() + ": no non-floodfill peers left, and no more pending.  Searched: "
                               + _state.getAttempted().size() + " failed: " + _state.getFailed().size());
@@ -273,8 +273,8 @@ class SearchJob extends JobImpl {
                 return;
             }
             List closestHashes = getClosestRouters(_state.getTarget(), toCheck, attempted);
-            if ( (closestHashes == null) || (closestHashes.size() <= 0) ) {
-                if (_state.getPending().size() <= 0) {
+            if ( (closestHashes == null) || (closestHashes.isEmpty()) ) {
+                if (_state.getPending().isEmpty()) {
                     // we tried to find some peers, but there weren't any and no one else is going to answer
                     if (_log.shouldLog(Log.INFO))
                         _log.info(getJobId() + ": No peers left, and none pending!  Already searched: " 
@@ -746,7 +746,7 @@ class SearchJob extends JobImpl {
     private void handleDeferred(boolean success) {
         List deferred = null;
         synchronized (_deferredSearches) {
-            if (_deferredSearches.size() > 0) {
+            if (!_deferredSearches.isEmpty()) {
                 deferred = new ArrayList(_deferredSearches);
                 _deferredSearches.clear();
             }
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/StoreJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/StoreJob.java
index 690f37b87fc48e0bb83330864f3ab3f715b9b54c..ad8217c6a7944319b2ee195015501445c4a456c8 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/StoreJob.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/StoreJob.java
@@ -151,8 +151,8 @@ class StoreJob extends JobImpl {
         //else
         //    closestHashes = getClosestRouters(_state.getTarget(), toCheck, _state.getAttempted());
         closestHashes = getClosestFloodfillRouters(_state.getTarget(), toCheck, _state.getAttempted());
-        if ( (closestHashes == null) || (closestHashes.size() <= 0) ) {
-            if (_state.getPending().size() <= 0) {
+        if ( (closestHashes == null) || (closestHashes.isEmpty()) ) {
+            if (_state.getPending().isEmpty()) {
                 if (_log.shouldLog(Log.INFO))
                     _log.info(getJobId() + ": No more peers left and none pending");
                 fail();
diff --git a/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java b/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java
index dbeee1a4dffbe292493ff38e75ccfbf6a45627ba..29fce33a6cb18e1664b2f61efff98151c36c0089 100644
--- a/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java
+++ b/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java
@@ -285,12 +285,12 @@ public class Reseeder {
     private static final String BUNDLE_NAME = "net.i2p.router.web.messages";
 
     /** translate */
-    public String _(String key) {
+    private String _(String key) {
         return Translate.getString(key, _context, BUNDLE_NAME);
     }
 
     /** translate */
-    public String _(String s, Object o, Object o2) {
+    private String _(String s, Object o, Object o2) {
         return Translate.getString(s, o, o2, _context, BUNDLE_NAME);
     }
 
diff --git a/router/java/src/net/i2p/router/peermanager/PeerManager.java b/router/java/src/net/i2p/router/peermanager/PeerManager.java
index 61f5c2062ebbb474d16d371342227e174ebaa395..bfe038e8c50266c7eaaab0d4ad11f5f1f4fe756d 100644
--- a/router/java/src/net/i2p/router/peermanager/PeerManager.java
+++ b/router/java/src/net/i2p/router/peermanager/PeerManager.java
@@ -226,7 +226,7 @@ class PeerManager {
         int index = _context.random().nextInt(Integer.MAX_VALUE);
         synchronized (_capabilitiesByPeer) {
             List peers = locked_getPeers(capability);
-            if ( (peers != null) && (peers.size() > 0) ) {
+            if ( (peers != null) && (!peers.isEmpty()) ) {
                 index = index % peers.size();
                 return (Hash)peers.get(index);
             }
diff --git a/router/java/src/net/i2p/router/startup/LoadClientAppsJob.java b/router/java/src/net/i2p/router/startup/LoadClientAppsJob.java
index 13dae3a157faa011b4548d56826f63074f6e0f3d..f737c452d5192372959bb05ce1d355341d351b59 100644
--- a/router/java/src/net/i2p/router/startup/LoadClientAppsJob.java
+++ b/router/java/src/net/i2p/router/startup/LoadClientAppsJob.java
@@ -30,7 +30,7 @@ public class LoadClientAppsJob extends JobImpl {
             _loaded = true;
         }
         List apps = ClientAppConfig.getClientApps(getContext());
-        if (apps.size() <= 0) {
+        if (apps.isEmpty()) {
             _log.error("Warning - No client apps or router console configured - we are just a router");
             System.err.println("Warning - No client apps or router console configured - we are just a router");
             return;
@@ -56,23 +56,26 @@ public class LoadClientAppsJob extends JobImpl {
         private String _args[];
         private Log _log;
         private ThreadGroup _threadGroup;
+        private ClassLoader _cl;
 
         public DelayedRunClient(RouterContext enclosingContext, String className, String clientName, String args[], long delay) {
-            this(enclosingContext, className, clientName, args, delay, null);
+            this(enclosingContext, className, clientName, args, delay, null, null);
         }
         
-        public DelayedRunClient(RouterContext enclosingContext, String className, String clientName, String args[], long delay, ThreadGroup threadGroup) {
+        public DelayedRunClient(RouterContext enclosingContext, String className, String clientName, String args[],
+                                long delay, ThreadGroup threadGroup, ClassLoader cl) {
             super(enclosingContext);
             _className = className;
             _clientName = clientName;
             _args = args;
             _log = enclosingContext.logManager().getLog(LoadClientAppsJob.class);
             _threadGroup = threadGroup;
+            _cl = cl;
             getTiming().setStartAfter(getContext().clock().now() + delay);
         }
         public String getName() { return "Delayed client job"; }
         public void runJob() {
-            runClient(_className, _clientName, _args, _log, _threadGroup);
+            runClient(_className, _clientName, _args, _log, _threadGroup, _cl);
         }
     }
     
@@ -129,50 +132,81 @@ public class LoadClientAppsJob extends JobImpl {
      *  to propagate an error back to the user,
      *  since runClient() runs in a separate thread.
      *
+     *  @param cl can be null
      *  @since 0.7.13
      */
-    public static void testClient(String className) throws ClassNotFoundException {
-        Class.forName(className);
+    public static void testClient(String className, ClassLoader cl) throws ClassNotFoundException {
+        if (cl == null)
+            cl = ClassLoader.getSystemClassLoader();
+        Class.forName(className, false, cl);
     }
 
     /**
      *  Run client in this thread.
      *
+     *  @param clientName can be null
+     *  @param args can be null
      *  @throws just about anything, caller would be wise to catch Throwable
      *  @since 0.7.13
      */
     public static void runClientInline(String className, String clientName, String args[], Log log) throws Exception {
+        runClientInline(className, clientName, args, log, null);
+    }
+
+    /**
+     *  Run client in this thread.
+     *
+     *  @param clientName can be null
+     *  @param args can be null
+     *  @param cl can be null
+     *  @throws just about anything, caller would be wise to catch Throwable
+     *  @since 0.7.14
+     */
+    public static void runClientInline(String className, String clientName, String args[],
+                                       Log log, ClassLoader cl) throws Exception {
         if (log.shouldLog(Log.INFO))
             log.info("Loading up the client application " + clientName + ": " + className + " " + Arrays.toString(args));
         if (args == null)
             args = new String[0];
-        Class cls = Class.forName(className);
+        Class cls = Class.forName(className, true, cl);
         Method method = cls.getMethod("main", new Class[] { String[].class });
         method.invoke(cls, new Object[] { args });
     }
 
     /**
      *  Run client in a new thread.
+     *
+     *  @param clientName can be null
+     *  @param args can be null
      */
     public static void runClient(String className, String clientName, String args[], Log log) {
-        runClient(className, clientName, args, log, null);
+        runClient(className, clientName, args, log, null, null);
     }
     
     /**
      *  Run client in a new thread.
+     *
+     *  @param clientName can be null
+     *  @param args can be null
+     *  @param threadGroup can be null
+     *  @param cl can be null
+     *  @since 0.7.13
      */
-    public static void runClient(String className, String clientName, String args[], Log log, ThreadGroup threadGroup) {
+    public static void runClient(String className, String clientName, String args[], Log log,
+                                 ThreadGroup threadGroup, ClassLoader cl) {
         if (log.shouldLog(Log.INFO))
             log.info("Loading up the client application " + clientName + ": " + className + " " + Arrays.toString(args));
         I2PThread t;
         if (threadGroup != null)
-            t = new I2PThread(threadGroup, new RunApp(className, clientName, args, log));
+            t = new I2PThread(threadGroup, new RunApp(className, clientName, args, log, cl));
         else
-            t = new I2PThread(new RunApp(className, clientName, args, log));
+            t = new I2PThread(new RunApp(className, clientName, args, log, cl));
         if (clientName == null) 
             clientName = className + " client";
         t.setName(clientName);
         t.setDaemon(true);
+        if (cl != null)
+            t.setContextClassLoader(cl);
         t.start();
     }
 
@@ -181,7 +215,9 @@ public class LoadClientAppsJob extends JobImpl {
         private String _appName;
         private String _args[];
         private Log _log;
-        public RunApp(String className, String appName, String args[], Log log) { 
+        private ClassLoader _cl;
+
+        public RunApp(String className, String appName, String args[], Log log, ClassLoader cl) { 
             _className = className; 
             _appName = appName;
             if (args == null)
@@ -189,10 +225,15 @@ public class LoadClientAppsJob extends JobImpl {
             else
                 _args = args;
             _log = log;
+            if (cl == null)
+                _cl = ClassLoader.getSystemClassLoader();
+            else
+                _cl = cl;
         }
+
         public void run() {
             try {
-                Class cls = Class.forName(_className);
+                Class cls = Class.forName(_className, true, _cl);
                 Method method = cls.getMethod("main", new Class[] { String[].class });
                 method.invoke(cls, new Object[] { _args });
             } catch (Throwable t) {
diff --git a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java
index 50fdd8ddc401a31e3ef170a371c2b6839c0392f1..3e5eafd74c9801cbfc9afcbf188dc56dc54be089 100644
--- a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java
+++ b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java
@@ -91,7 +91,7 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
         }
         Vector skews = _manager.getClockSkews();
         if (skews == null ||
-            skews.size() <= 0 ||
+            skews.isEmpty() ||
             (skews.size() < 5 && _context.clock().getUpdatedSuccessfully())) {
             return _context.clock().getOffset();
         }
diff --git a/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java b/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java
index e9cde0b9c70fe536db3d7d1e7f57b80317f0fd70..112d3660140285009f309d4c48794e7f02721472 100644
--- a/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java
+++ b/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java
@@ -443,7 +443,7 @@ public class FIFOBandwidthLimiter {
      *
      */
     private final void locked_satisfyInboundUnlimited(List<Request> satisfied) {
-        while (_pendingInboundRequests.size() > 0) {
+        while (!_pendingInboundRequests.isEmpty()) {
             SimpleRequest req = (SimpleRequest)_pendingInboundRequests.remove(0);
             int allocated = req.getPendingInboundRequested();
             _totalAllocatedInboundBytes.addAndGet(allocated);
@@ -558,7 +558,7 @@ public class FIFOBandwidthLimiter {
      *
      */
     private final void locked_satisfyOutboundUnlimited(List<Request> satisfied) {
-        while (_pendingOutboundRequests.size() > 0) {
+        while (!_pendingOutboundRequests.isEmpty()) {
             SimpleRequest req = (SimpleRequest)_pendingOutboundRequests.remove(0);
             int allocated = req.getPendingOutboundRequested();
             _totalAllocatedOutboundBytes.addAndGet(allocated);
diff --git a/router/java/src/net/i2p/router/transport/OutboundMessageRegistry.java b/router/java/src/net/i2p/router/transport/OutboundMessageRegistry.java
index 17108a8e87c2cf67dd28d8f6c4f10af24dafad0a..b8261d1d2bec8b703016eafff2409e0c37328221 100644
--- a/router/java/src/net/i2p/router/transport/OutboundMessageRegistry.java
+++ b/router/java/src/net/i2p/router/transport/OutboundMessageRegistry.java
@@ -185,7 +185,7 @@ public class OutboundMessageRegistry {
                 if (old instanceof List) {
                     List l = (List)old;
                     l.remove(msg);
-                    if (l.size() > 0) {
+                    if (!l.isEmpty()) {
                         _selectorToMessage.put(sel, l);
                         stillActive = true;
                     }
@@ -221,7 +221,7 @@ public class OutboundMessageRegistry {
                     }
                 }
             }
-            if (removing.size() > 0) {
+            if (!removing.isEmpty()) {
                 for (int i = 0; i < removing.size(); i++) {
                     MessageSelector sel = (MessageSelector)removing.get(i);
                     OutNetMessage msg = null;
diff --git a/router/java/src/net/i2p/router/transport/TransportImpl.java b/router/java/src/net/i2p/router/transport/TransportImpl.java
index e046cdde81b4e9827f881dabc8d1d8afd3127dc2..77604083e931330c1893719a42905ba209d565c9 100644
--- a/router/java/src/net/i2p/router/transport/TransportImpl.java
+++ b/router/java/src/net/i2p/router/transport/TransportImpl.java
@@ -147,7 +147,7 @@ public abstract class TransportImpl implements Transport {
     public OutNetMessage getNextMessage() {
         OutNetMessage msg = null;
         synchronized (_sendPool) {
-            if (_sendPool.size() <= 0) return null;
+            if (_sendPool.isEmpty()) return null;
             msg = (OutNetMessage)_sendPool.remove(0); // use priority queues later
         }
         msg.beginSend();
diff --git a/router/java/src/net/i2p/router/transport/TransportManager.java b/router/java/src/net/i2p/router/transport/TransportManager.java
index a479ad52f932add0b7f5807217d526b4c13f7435..a4088b715b547aeec236adb43149a904af05c463 100644
--- a/router/java/src/net/i2p/router/transport/TransportManager.java
+++ b/router/java/src/net/i2p/router/transport/TransportManager.java
@@ -84,7 +84,7 @@ public class TransportManager implements TransportEventListener {
         }
         if (enableNTCP(_context))
             addTransport(new NTCPTransport(_context));
-        if (_transports.size() <= 0)
+        if (_transports.isEmpty())
             _log.log(Log.CRIT, "No transports are enabled");
     }
     
@@ -223,7 +223,7 @@ public class TransportManager implements TransportEventListener {
       * Use for throttling in the router.
       */
     public boolean haveHighOutboundCapacity() { 
-        if (_transports.size() <= 0)
+        if (_transports.isEmpty())
             return false;
         for (int i = 0; i < _transports.size(); i++) {
             if (!_transports.get(i).haveCapacity(HIGH_CAPACITY_PCT))
@@ -255,7 +255,7 @@ public class TransportManager implements TransportEventListener {
         Vector skews = new Vector();
         for (int i = 0; i < _transports.size(); i++) {
             Vector tempSkews = _transports.get(i).getClockSkews();
-            if ((tempSkews == null) || (tempSkews.size() <= 0)) continue;
+            if ((tempSkews == null) || (tempSkews.isEmpty())) continue;
             skews.addAll(tempSkews);
         }
         if (_log.shouldLog(Log.DEBUG))
@@ -373,7 +373,7 @@ public class TransportManager implements TransportEventListener {
     
     public TransportBid getBid(OutNetMessage msg) {
         List<TransportBid> bids = getBids(msg);
-        if ( (bids == null) || (bids.size() <= 0) )
+        if ( (bids == null) || (bids.isEmpty()) )
             return null;
         else
             return bids.get(0);
diff --git a/router/java/src/net/i2p/router/transport/UPnP.java b/router/java/src/net/i2p/router/transport/UPnP.java
index 0fc538a3f3503ddbe3510650426b308f24dc82d5..aa2261cfc779527ce8ce4e578dc219b78ae8485e 100644
--- a/router/java/src/net/i2p/router/transport/UPnP.java
+++ b/router/java/src/net/i2p/router/transport/UPnP.java
@@ -391,7 +391,7 @@ public class UPnP extends ControlPoint implements DeviceChangeListener, EventLis
 	// TODO: extend it! RTFM
 	private void listSubServices(Device dev, StringBuilder sb) {
 		ServiceList sl = dev.getServiceList();
-		if (sl.size() <= 0)
+		if (sl.isEmpty())
 			return;
 		sb.append("<ul>\n");
 		for(int i=0; i<sl.size(); i++) {
@@ -440,7 +440,7 @@ public class UPnP extends ControlPoint implements DeviceChangeListener, EventLis
 		listSubServices(dev, sb);
 		
 		DeviceList dl = dev.getDeviceList();
-		if (dl.size() <= 0)
+		if (dl.isEmpty())
 			return;
 		sb.append("<ul>\n");
 		for(int j=0; j<dl.size(); j++) {
diff --git a/router/java/src/net/i2p/router/transport/ntcp/NTCPConnection.java b/router/java/src/net/i2p/router/transport/ntcp/NTCPConnection.java
index 043fb18c26af697b09d4b818198aac56f98cb795..52c0218fc77501e3c34fbbcf8e5d47cdb2e7e0f0 100644
--- a/router/java/src/net/i2p/router/transport/ntcp/NTCPConnection.java
+++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPConnection.java
@@ -487,7 +487,7 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener {
                 return;
             }
                 //throw new RuntimeException("We should not be preparing a write while we still have one pending");
-            if (_outbound.size() > 0) {
+            if (!_outbound.isEmpty()) {
                 msg = (OutNetMessage)_outbound.remove(0);
                 _currentOutbound = msg;
             } else {
@@ -711,7 +711,7 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener {
     private final static List _bufs = new ArrayList(NUM_PREP_BUFS);
     private PrepBuffer acquireBuf() {
         synchronized (_bufs) {
-            if (_bufs.size() > 0) {
+            if (!_bufs.isEmpty()) {
                 PrepBuffer b = (PrepBuffer)_bufs.remove(0);
                 b.acquired();
                 return b;
diff --git a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
index 779fd97e4f1cb60cac5a9bd48936ecc5bf5184ab..fea56423b65ba3674d294a9a2908296652a767b7 100644
--- a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
+++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
@@ -559,7 +559,7 @@ public class NTCPTransport extends TransportImpl {
         }
         for (int i = 0; expired != null && i < expired.size(); i++)
             ((NTCPConnection)expired.get(i)).close();
-        if ( (expired != null) && (expired.size() > 0) )
+        if ( (expired != null) && (!expired.isEmpty()) )
             _context.statManager().addRateData("ntcp.outboundEstablishFailed", expired.size(), 0);
     }
 
@@ -763,12 +763,12 @@ public class NTCPTransport extends TransportImpl {
             buf.setLength(0);
         }
 
-        if (peers.size() > 0) {
+        if (!peers.isEmpty()) {
 //            buf.append("<tr> <td colspan=\"11\"><hr></td></tr>\n");
             buf.append("<tr class=\"tablefooter\"><td align=\"center\"><b>").append(peers.size()).append(' ').append(_("peers")).append("</b></td><td>&nbsp;</td><td>&nbsp;");
             buf.append("</td><td align=\"center\"><b>").append(formatRate(bpsRecv/1024)).append("/").append(formatRate(bpsSend/1024)).append("</b>");
             buf.append("</td><td align=\"center\"><b>").append(DataHelper.formatDuration(totalUptime/peers.size()));
-            buf.append("</b></td><td align=\"center\"><b>").append(peers.size() > 0 ? DataHelper.formatDuration(offsetTotal*1000/peers.size()) : "0ms");
+            buf.append("</b></td><td align=\"center\"><b>").append((!peers.isEmpty()) ? DataHelper.formatDuration(offsetTotal*1000/peers.size()) : "0ms");
             buf.append("</b></td><td align=\"center\"><b>").append(totalSend).append("</b></td><td align=\"center\"><b>").append(totalRecv);
             buf.append("</b></td><td>&nbsp;</td><td>&nbsp;</td></tr>\n");
         }
diff --git a/router/java/src/net/i2p/router/transport/ntcp/Reader.java b/router/java/src/net/i2p/router/transport/ntcp/Reader.java
index c0f77c1a8560fb46b630551dbe0ae0305aca39bd..ce21e13c315ad596f63f8b0780f58d9cd2f23652 100644
--- a/router/java/src/net/i2p/router/transport/ntcp/Reader.java
+++ b/router/java/src/net/i2p/router/transport/ntcp/Reader.java
@@ -40,7 +40,7 @@ class Reader {
         }
     }
     public void stopReading() {
-        while (_runners.size() > 0) {
+        while (!_runners.isEmpty()) {
             Runner r = _runners.remove(0);
             r.stop();
         }
@@ -90,7 +90,7 @@ class Reader {
                         } else {
                             _liveReads.remove(con);
                             con = null;
-                            if (_pendingConnections.size() <= 0) {
+                            if (_pendingConnections.isEmpty()) {
                                 _pendingConnections.wait();
                             } else {
                                 con = _pendingConnections.remove(0);
diff --git a/router/java/src/net/i2p/router/transport/ntcp/Writer.java b/router/java/src/net/i2p/router/transport/ntcp/Writer.java
index 45efc30553d2c765bb415145703a4355614876f7..ca676c572ce5c4dc7a6572f964d8ec918338ee34 100644
--- a/router/java/src/net/i2p/router/transport/ntcp/Writer.java
+++ b/router/java/src/net/i2p/router/transport/ntcp/Writer.java
@@ -39,7 +39,7 @@ class Writer {
         }
     }
     public void stopWriting() {
-        while (_runners.size() > 0) {
+        while (!_runners.isEmpty()) {
             Runner r = _runners.remove(0);
             r.stop();
         }
@@ -95,7 +95,7 @@ class Writer {
                         } else {
                             _liveWrites.remove(con);
                             con = null;
-                            if (_pendingConnections.size() <= 0) {
+                            if (_pendingConnections.isEmpty()) {
                                 if (_log.shouldLog(Log.DEBUG))
                                     _log.debug("Done writing, but nothing pending, so wait");
                                 _pendingConnections.wait();
diff --git a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
index 64e1bdea2df425b95342d72aa22c55eebe1ea061..1a99c095cdcf01daa2443efbdbd20bccdbe21eec 100644
--- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
+++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
@@ -359,14 +359,14 @@ public class EstablishmentManager {
 /********
     private int locked_admitQueued() {
         int admitted = 0;
-        while ( (_queuedOutbound.size() > 0) && (_outboundStates.size() < getMaxConcurrentEstablish()) ) {
+        while ( (!_queuedOutbound.isEmpty()) && (_outboundStates.size() < getMaxConcurrentEstablish()) ) {
             // ok, active shrunk, lets let some queued in.  duplicate the synchronized 
             // section from the add(
 
             RemoteHostId to = (RemoteHostId)_queuedOutbound.keySet().iterator().next();
             List queued = (List)_queuedOutbound.remove(to);
 
-            if (queued.size() <= 0)
+            if (queued.isEmpty())
                 continue;
             
             OutNetMessage msg = (OutNetMessage)queued.get(0);
diff --git a/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java b/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java
index 4b16d078dae7bda704376d642aa9e60045389086..53791ffa99ef85e76e215dab1c2baa18f6b51dc0 100644
--- a/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java
+++ b/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java
@@ -131,7 +131,7 @@ public class PacketBuilder {
             }
         }
 
-        if ( (partialACKsRemaining != null) && (partialACKsRemaining.size() > 0) ) {
+        if ( (partialACKsRemaining != null) && (!partialACKsRemaining.isEmpty()) ) {
             int origNumRemaining = partialACKsRemaining.size();
             int numPartialOffset = off;
             // leave it blank for now, since we could skip some
diff --git a/router/java/src/net/i2p/router/transport/udp/PeerState.java b/router/java/src/net/i2p/router/transport/udp/PeerState.java
index 06e528a944c0978e3b243b97e1d12fc2883f1c1c..86b3aad6eee127045bd2f2a40b8f38b4605158d0 100644
--- a/router/java/src/net/i2p/router/transport/udp/PeerState.java
+++ b/router/java/src/net/i2p/router/transport/udp/PeerState.java
@@ -749,7 +749,7 @@ public class PeerState {
             }
             if (_currentACKs.isEmpty())
                 _wantACKSendSince = -1;
-            if (alwaysIncludeRetransmissions || rv.size() > 0) {
+            if (alwaysIncludeRetransmissions || !rv.isEmpty()) {
                 // now repeat by putting in some old ACKs
                 // randomly selected from the Resend queue.
                 // Maybe we should only resend each one a certain number of times...
diff --git a/router/java/src/net/i2p/router/transport/udp/UDPFlooder.java b/router/java/src/net/i2p/router/transport/udp/UDPFlooder.java
index 38bf62246e902d8f53d85cf9b1a0358c3352479f..aa34b1a4bff4c01d93cc0003fddc7d901150a343 100644
--- a/router/java/src/net/i2p/router/transport/udp/UDPFlooder.java
+++ b/router/java/src/net/i2p/router/transport/udp/UDPFlooder.java
@@ -66,7 +66,7 @@ class UDPFlooder implements Runnable {
         while (_alive) {
             try {
                 synchronized (_peers) {
-                    if (_peers.size() <= 0)
+                    if (_peers.isEmpty())
                         _peers.wait();
                 }
             } catch (InterruptedException ie) {}
diff --git a/router/java/src/net/i2p/router/transport/udp/UDPSender.java b/router/java/src/net/i2p/router/transport/udp/UDPSender.java
index 6d1cd7c3a7ba4fe1fffdb75ee571abb011bd3931..745b50df4b57b35ae11686cdc2048e782b9cb91e 100644
--- a/router/java/src/net/i2p/router/transport/udp/UDPSender.java
+++ b/router/java/src/net/i2p/router/transport/udp/UDPSender.java
@@ -106,12 +106,12 @@ public class UDPSender {
                 synchronized (_outboundQueue) {
                     // clear out any too-old packets
                     UDPPacket head = null;
-                    if (_outboundQueue.size() > 0) {
+                    if (!_outboundQueue.isEmpty()) {
                         head = (UDPPacket)_outboundQueue.get(0);
                         while (head.getLifetime() > MAX_HEAD_LIFETIME) {
                             _outboundQueue.remove(0);
                             removed++;
-                            if (_outboundQueue.size() > 0)
+                            if (!_outboundQueue.isEmpty())
                                 head = (UDPPacket)_outboundQueue.get(0);
                             else
                                 break;
diff --git a/router/java/src/net/i2p/router/tunnel/BatchedPreprocessor.java b/router/java/src/net/i2p/router/tunnel/BatchedPreprocessor.java
index 879eb78e70cf09eaa9c3fba4cd9393a54a66a5bb..4533956d37939dc2a8360d3bc8c73fac1c74a0b3 100644
--- a/router/java/src/net/i2p/router/tunnel/BatchedPreprocessor.java
+++ b/router/java/src/net/i2p/router/tunnel/BatchedPreprocessor.java
@@ -137,7 +137,7 @@ public class BatchedPreprocessor extends TrivialPreprocessor {
         int beforeLooping = pending.size();
         
         // loop until the queue is empty
-        while (pending.size() > 0) {
+        while (!pending.isEmpty()) {
             int allocated = 0;
             long beforePendingLoop = System.currentTimeMillis();
 
@@ -252,7 +252,7 @@ public class BatchedPreprocessor extends TrivialPreprocessor {
                         _context.statManager().addRateData("tunnel.writeDelay", cur.getLifetime(), cur.getData().length);
                     }
 
-                    if (pending.size() > 0) {
+                    if (!pending.isEmpty()) {
                         // rare
                         _pendingSince = _context.clock().now();
                         _context.statManager().addRateData("tunnel.batchFlushRemaining", pending.size(), beforeSize);
diff --git a/router/java/src/net/i2p/router/tunnel/PumpedTunnelGateway.java b/router/java/src/net/i2p/router/tunnel/PumpedTunnelGateway.java
index fddb30d2caa27c221212b2896ff8ac4cfbe21046..a761ef12081908fcb58caed4039b1af882ab95fe 100644
--- a/router/java/src/net/i2p/router/tunnel/PumpedTunnelGateway.java
+++ b/router/java/src/net/i2p/router/tunnel/PumpedTunnelGateway.java
@@ -85,7 +85,7 @@ public class PumpedTunnelGateway extends TunnelGateway {
      */
     void pump(List<Pending> queueBuf) {
         synchronized (_prequeue) {
-            if (_prequeue.size() > 0) {
+            if (!_prequeue.isEmpty()) {
                 queueBuf.addAll(_prequeue);
                 _prequeue.clear();
             } else {
diff --git a/router/java/src/net/i2p/router/tunnel/TrivialPreprocessor.java b/router/java/src/net/i2p/router/tunnel/TrivialPreprocessor.java
index 3dac4dd205cbcae3206296834459719001243730..c9b28b85629fe8a448115d21b7da411deba14b95 100644
--- a/router/java/src/net/i2p/router/tunnel/TrivialPreprocessor.java
+++ b/router/java/src/net/i2p/router/tunnel/TrivialPreprocessor.java
@@ -59,7 +59,7 @@ public class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
             buf = new StringBuilder(256);
             buf.append("Trivial preprocessing of ").append(pending.size()).append(" ");
         }
-        while (pending.size() > 0) {
+        while (!pending.isEmpty()) {
             TunnelGateway.Pending msg = pending.remove(0);
             long beforePreproc = System.currentTimeMillis();
             byte preprocessed[][] = preprocess(msg);
diff --git a/router/java/src/net/i2p/router/tunnel/TunnelDispatcher.java b/router/java/src/net/i2p/router/tunnel/TunnelDispatcher.java
index 7dfbded7d854dc41b97060b1331a33ae8010a3e5..b7659077cc144ef582430f0c617f7d34abbe6b20 100644
--- a/router/java/src/net/i2p/router/tunnel/TunnelDispatcher.java
+++ b/router/java/src/net/i2p/router/tunnel/TunnelDispatcher.java
@@ -649,7 +649,7 @@ public class TunnelDispatcher implements Service {
     public void dropBiggestParticipating() {
 
        List<HopConfig> partTunnels = listParticipatingTunnels();
-       if ((partTunnels == null) || (partTunnels.size() == 0)) {
+       if ((partTunnels == null) || (partTunnels.isEmpty())) {
            if (_log.shouldLog(Log.ERROR))
                _log.error("Not dropping tunnel, since partTunnels was null or had 0 items!");
            return;
@@ -745,7 +745,7 @@ public class TunnelDispatcher implements Service {
             Long dropTime = new Long(cfg.getExpiration() + 2*Router.CLOCK_FUDGE_FACTOR + LEAVE_BATCH_TIME);
             boolean noTunnels;
             synchronized (LeaveTunnel.this) {
-                noTunnels = _configs.size() <= 0;
+                noTunnels = _configs.isEmpty();
                 _configs.add(cfg);
                 _times.add(dropTime);
             
@@ -777,13 +777,13 @@ public class TunnelDispatcher implements Service {
             long now = getContext().clock().now() + LEAVE_BATCH_TIME; // leave all expiring in next 10 sec
             while (true) {
                 synchronized (LeaveTunnel.this) {
-                    if (_configs.size() <= 0)
+                    if (_configs.isEmpty())
                         return;
                     nextTime = _times.get(0);
                     if (nextTime.longValue() <= now) {
                         cur = _configs.remove(0);
                         _times.remove(0);
-                        if (_times.size() > 0)
+                        if (!_times.isEmpty())
                             nextTime = _times.get(0);
                         else
                             nextTime = null;
diff --git a/router/java/src/net/i2p/router/tunnel/TunnelGateway.java b/router/java/src/net/i2p/router/tunnel/TunnelGateway.java
index bf093f7a261965a1ede21a74b36bc8e8aed73f1a..7291c8706a3207f7b07fda16c4b213874e4ac25f 100644
--- a/router/java/src/net/i2p/router/tunnel/TunnelGateway.java
+++ b/router/java/src/net/i2p/router/tunnel/TunnelGateway.java
@@ -294,7 +294,7 @@ public class TunnelGateway {
                 //if (_queue.size() > 10000) // stay in the synchronized block
                 //    System.out.println("foo!");
                 afterChecked = _context.clock().now();
-                if (_queue.size() > 0) {
+                if (!_queue.isEmpty()) {
                     if ( (remaining > 0) && (_log.shouldLog(Log.DEBUG)) )
                         _log.debug("Remaining before delayed flush preprocessing: " + _queue);
                     wantRequeue = _preprocessor.preprocessQueue(_queue, _sender, _receiver);
diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java b/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java
index aa6417fdac45334f7e4d3986cec971a4a9cc9942..8b08b6ec8cf5ed3d4e296e42bc609d243f7950fb 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java
@@ -298,7 +298,7 @@ class BuildExecutor implements Runnable {
                         }
                     }
                 } else {
-                    if ( (allowed > 0) && (wanted.size() > 0) ) {
+                    if ( (allowed > 0) && (!wanted.isEmpty()) ) {
                         Collections.shuffle(wanted, _context.random());
                         Collections.sort(wanted, new TunnelPoolComparator());
 
@@ -307,7 +307,7 @@ class BuildExecutor implements Runnable {
                         if (allowed > 2)
                             allowed = 2;
                         
-                        for (int i = 0; (i < allowed) && (wanted.size() > 0); i++) {
+                        for (int i = 0; (i < allowed) && (!wanted.isEmpty()); i++) {
                             TunnelPool pool = wanted.remove(0);
                             //if (pool.countWantedTunnels() <= 0)
                             //    continue;
diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java b/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java
index 01eb674f4dbaad73883f716936c557f673f9da54..705552c19060a3c62736211032b872bed7ee1bad 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java
@@ -139,14 +139,14 @@ class BuildHandler {
                         } else {
                             break;
                         }
-                    } while (_inboundBuildMessages.size() > 0);
+                    } while (!_inboundBuildMessages.isEmpty());
                     
                     if (dropExpired > 0)
                         _context.throttle().setTunnelStatus(_x("Dropping tunnel requests: Too slow"));
 
                     // now pull off the oldest requests first (we're doing a tail-drop
                     // when adding)
-                    for (int i = 0; i < toHandle && _inboundBuildMessages.size() > 0; i++)
+                    for (int i = 0; i < toHandle && !_inboundBuildMessages.isEmpty(); i++)
                         handled.add(_inboundBuildMessages.remove(0));
                 //}
             }
diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java
index d116431a473053de1cfd1bff6a858da4ad008234..e6f3e599e8bf4c70b16c7f282529b748cdb476c5 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java
@@ -152,7 +152,7 @@ public class TunnelPool {
             _lastSelectionPeriod = period;
             _lastSelected = null;
 
-            if (_tunnels.size() <= 0) {
+            if (_tunnels.isEmpty()) {
                 if (_log.shouldLog(Log.WARN))
                     _log.warn(toString() + ": No tunnels to select from");
             } else {
@@ -483,7 +483,7 @@ public class TunnelPool {
             if (_log.shouldLog(Log.WARN))
                 _log.warn(toString() + ": Not enough tunnels (" + _tunnels.size() + ", wanted " + wanted + ")");
             // see comment below
-            if (_tunnels.size() <= 0)
+            if (_tunnels.isEmpty())
                 return null;
         }
 
@@ -538,7 +538,7 @@ public class TunnelPool {
         if (leases.size() < wanted) {
             if (_log.shouldLog(Log.WARN))
                 _log.warn(toString() + ": Not enough leases (" + leases.size() + ", wanted " + wanted + ")");
-            if (leases.size() <= 0)
+            if (leases.isEmpty())
                 return null;
         }
 
@@ -858,7 +858,7 @@ public class TunnelPool {
 
         if (!forceZeroHop) {
             peers = _peerSelector.selectPeers(_context, settings);
-            if ( (peers == null) || (peers.size() <= 0) ) {
+            if ( (peers == null) || (peers.isEmpty()) ) {
                 // no inbound or outbound tunnels to send the request through, and 
                 // the pool is refusing 0 hop tunnels
                 if (peers == null) {