diff --git a/core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java b/core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java
index 192bde062920e187cb639320e498a6756f5934de..160cc1354bb54a5d5e2c3948f65574b7eae05aaa 100644
--- a/core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java
+++ b/core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java
@@ -82,7 +82,9 @@ public class DHSessionKeyBuilder {
 
         // add to the defaults for every 128MB of RAM, up to 512MB
         long maxMemory = Runtime.getRuntime().maxMemory();
-        int factor = Math.min(4, (int) (1 + (maxMemory / (128*1024*1024l))));
+        if (maxMemory == Long.MAX_VALUE)
+            maxMemory = 127*1024*1024l;
+        int factor = (int) Math.max(1l, Math.min(4l, 1 + (maxMemory / (128*1024*1024l))));
         int defaultMin = DEFAULT_DH_PRECALC_MIN * factor;
         int defaultMax = DEFAULT_DH_PRECALC_MAX * factor;
         MIN_NUM_BUILDERS = ctx.getProperty(PROP_DH_PRECALC_MIN, defaultMin);
diff --git a/core/java/src/net/i2p/crypto/YKGenerator.java b/core/java/src/net/i2p/crypto/YKGenerator.java
index 165749a7cf52aecf92ac9131fb346e013edae69a..ef8546e2f0f415225669fc213101fbf3488ababe 100644
--- a/core/java/src/net/i2p/crypto/YKGenerator.java
+++ b/core/java/src/net/i2p/crypto/YKGenerator.java
@@ -60,7 +60,9 @@ class YKGenerator {
 
         // add to the defaults for every 128MB of RAM, up to 1GB
         long maxMemory = Runtime.getRuntime().maxMemory();
-        int factor = Math.min(8, (int) (1 + (maxMemory / (128*1024*1024l))));
+        if (maxMemory == Long.MAX_VALUE)
+            maxMemory = 127*1024*1024l;
+        int factor = (int) Math.max(1l, Math.min(8l, 1 + (maxMemory / (128*1024*1024l))));
         int defaultMin = DEFAULT_YK_PRECALC_MIN * factor;
         int defaultMax = DEFAULT_YK_PRECALC_MAX * factor;
         MIN_NUM_BUILDERS = ctx.getProperty(PROP_YK_PRECALC_MIN, defaultMin);
diff --git a/core/java/src/net/i2p/data/DataHelper.java b/core/java/src/net/i2p/data/DataHelper.java
index 4e3db770b0674ac6785094181ed6bcee2592ba18..1aa5e90405b9e243bbddb817bd7faec2c296b5c5 100644
--- a/core/java/src/net/i2p/data/DataHelper.java
+++ b/core/java/src/net/i2p/data/DataHelper.java
@@ -1195,6 +1195,10 @@ public class DataHelper {
             case 2: return str + "M";
             case 3: return str + "G";
             case 4: return str + "T";
+            case 5: return str + "P";
+            case 6: return str + "E";
+            case 7: return str + "Z";
+            case 8: return str + "Y";
             default: return bytes + "";
         }
     }
@@ -1221,12 +1225,17 @@ public class DataHelper {
             case 2: return str + " M";
             case 3: return str + " G";
             case 4: return str + " T";
+            case 5: return str + " P";
+            case 6: return str + " E";
+            case 7: return str + " Z";
+            case 8: return str + " Y";
             default: return bytes + " ";
         }
     }
     
     /**
      * Strip out any HTML (simply removing any less than / greater than symbols)
+     * @param orig may be null, returns empty string if null
      */
     public static String stripHTML(String orig) {
         if (orig == null) return "";
diff --git a/core/java/src/net/i2p/data/RouterInfo.java b/core/java/src/net/i2p/data/RouterInfo.java
index b4aae94b1819f54ed30ffada1714501da8600d0d..7d6ff8a8e5b2f5f9288fad7faaef4550214499d4 100644
--- a/core/java/src/net/i2p/data/RouterInfo.java
+++ b/core/java/src/net/i2p/data/RouterInfo.java
@@ -52,7 +52,8 @@ public class RouterInfo extends DatabaseEntry {
     /** should we cache the byte and string versions _byteified ? **/
     private boolean _shouldCache;
     /** maybe we should check if we are floodfill? */
-    private static final boolean CACHE_ALL = Runtime.getRuntime().maxMemory() > 128*1024*1024l;
+    private static final boolean CACHE_ALL = Runtime.getRuntime().maxMemory() > 128*1024*1024l &&
+                                             Runtime.getRuntime().maxMemory() < Long.MAX_VALUE;
 
     public static final String PROP_NETWORK_ID = "netId";
     public static final String PROP_CAPABILITIES = "caps";
diff --git a/core/java/src/net/i2p/data/SDSCache.java b/core/java/src/net/i2p/data/SDSCache.java
index 562c49c79ae0ca8d880e0022fed1c619f8392d8f..8698f6a78b7d80c9ce89b4d18f480099412f4025 100644
--- a/core/java/src/net/i2p/data/SDSCache.java
+++ b/core/java/src/net/i2p/data/SDSCache.java
@@ -50,6 +50,8 @@ public class SDSCache<V extends SimpleDataStructure> {
     private static final double FACTOR;
     static {
         long maxMemory = Runtime.getRuntime().maxMemory();
+        if (maxMemory == Long.MAX_VALUE)
+            maxMemory = 96*1024*1024l;
         FACTOR = Math.max(MIN_FACTOR, Math.min(MAX_FACTOR, maxMemory / (128*1024*1024d)));
     }
 
diff --git a/core/java/src/net/i2p/util/ByteCache.java b/core/java/src/net/i2p/util/ByteCache.java
index 3ef72ca10c3ca55d352223eee1868403269e0730..2d3eb482db5b9f64a259e132fca70d1aeb53ae6e 100644
--- a/core/java/src/net/i2p/util/ByteCache.java
+++ b/core/java/src/net/i2p/util/ByteCache.java
@@ -69,6 +69,8 @@ public final class ByteCache {
     private static final int MAX_CACHE;
     static {
         long maxMemory = Runtime.getRuntime().maxMemory();
+        if (maxMemory == Long.MAX_VALUE)
+            maxMemory = 96*1024*1024l;
         MAX_CACHE = (int) Math.min(4*1024*1024l, Math.max(128*1024l, maxMemory / 128));
     }
 
diff --git a/core/java/src/net/i2p/util/SimpleScheduler.java b/core/java/src/net/i2p/util/SimpleScheduler.java
index 951f5929eb5cf6c1489ad053f203f3dc4983e4ac..61e2e66b347bcb3e823e8a4bf815ef6a9234bfec 100644
--- a/core/java/src/net/i2p/util/SimpleScheduler.java
+++ b/core/java/src/net/i2p/util/SimpleScheduler.java
@@ -43,6 +43,8 @@ public class SimpleScheduler {
         _log = _context.logManager().getLog(SimpleScheduler.class);
         _name = name;
         long maxMemory = Runtime.getRuntime().maxMemory();
+        if (maxMemory == Long.MAX_VALUE)
+            maxMemory = 96*1024*1024l;
         _threads = (int) Math.max(MIN_THREADS, Math.min(MAX_THREADS, 1 + (maxMemory / (32*1024*1024))));
         _executor = new ScheduledThreadPoolExecutor(_threads, new CustomThreadFactory());
         _executor.prestartAllCoreThreads();
diff --git a/core/java/src/net/i2p/util/SimpleTimer.java b/core/java/src/net/i2p/util/SimpleTimer.java
index ee3f35120f9b37363d1163cb9b4287706e740229..b19b5d691ac542a585a19a8a783878de3c7ad2f1 100644
--- a/core/java/src/net/i2p/util/SimpleTimer.java
+++ b/core/java/src/net/i2p/util/SimpleTimer.java
@@ -44,6 +44,8 @@ public class SimpleTimer {
         runner.setDaemon(true);
         runner.start();
         long maxMemory = Runtime.getRuntime().maxMemory();
+        if (maxMemory == Long.MAX_VALUE)
+            maxMemory = 128*1024*1024l;
         int threads = (int) Math.max(MIN_THREADS, Math.min(MAX_THREADS, 1 + (maxMemory / (32*1024*1024))));
         for (int i = 1; i <= threads ; i++) {
             I2PThread executor = new I2PThread(new Executor(_context, _log, _readyEvents, runn));
diff --git a/core/java/src/net/i2p/util/SimpleTimer2.java b/core/java/src/net/i2p/util/SimpleTimer2.java
index a497915e2358e4db6081a1c91fa5fd54559d27e2..955f8faa3a3b034c218c523232aa07d8d23a8477 100644
--- a/core/java/src/net/i2p/util/SimpleTimer2.java
+++ b/core/java/src/net/i2p/util/SimpleTimer2.java
@@ -43,6 +43,8 @@ public class SimpleTimer2 {
         _name = name;
         _count = 0;
         long maxMemory = Runtime.getRuntime().maxMemory();
+        if (maxMemory == Long.MAX_VALUE)
+            maxMemory = 96*1024*1024l;
         _threads = (int) Math.max(MIN_THREADS, Math.min(MAX_THREADS, 1 + (maxMemory / (32*1024*1024))));
         _executor = new CustomScheduledThreadPoolExecutor(_threads, new CustomThreadFactory());
         _executor.prestartAllCoreThreads();
diff --git a/router/java/src/net/i2p/router/JobQueue.java b/router/java/src/net/i2p/router/JobQueue.java
index 70a1b3bfef23d89cf47f839eab4911152bd2ce75..7f5cb008fe2fb53dbc4dbab50b393059f7c1afc4 100644
--- a/router/java/src/net/i2p/router/JobQueue.java
+++ b/router/java/src/net/i2p/router/JobQueue.java
@@ -61,6 +61,8 @@ public class JobQueue {
     private static final int RUNNERS;
     static {
         long maxMemory = Runtime.getRuntime().maxMemory();
+        if (maxMemory == Long.MAX_VALUE)
+            maxMemory = 128*1024*1024l;
         if (maxMemory < 64*1024*1024)
             RUNNERS = 3;
         else if (maxMemory < 256*1024*1024)
diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java
index 5904d04ea0b6bc0412086b16ff3e98d1a7844696..79f05bbd461aaea61b96fefe952fe34c47500120 100644
--- a/router/java/src/net/i2p/router/Router.java
+++ b/router/java/src/net/i2p/router/Router.java
@@ -1432,7 +1432,10 @@ private static class CoalesceStatsEvent implements SimpleTimer.TimedEvent {
         ctx.statManager().createRateStat("router.highCapacityPeers", "How many high capacity peers we know", "Throttle", new long[] { 5*60*1000, 60*60*1000 });
         ctx.statManager().createRateStat("router.fastPeers", "How many fast peers we know", "Throttle", new long[] { 5*60*1000, 60*60*1000 });
         _maxMemory = Runtime.getRuntime().maxMemory();
-        ctx.statManager().createRateStat("router.memoryUsed", "(Bytes) Max is " + (_maxMemory / (1024*1024)) + "MB", "Router", new long[] { 60*1000 });
+        String legend = "(Bytes)";
+        if (_maxMemory < Long.MAX_VALUE)
+            legend += " Max is " + DataHelper.formatSize(_maxMemory) + 'B';
+        ctx.statManager().createRateStat("router.memoryUsed", legend, "Router", new long[] { 60*1000 });
     }
     private RouterContext getContext() { return _ctx; }
     public void timeReached() {
diff --git a/router/java/src/net/i2p/router/RouterContext.java b/router/java/src/net/i2p/router/RouterContext.java
index ee891b230bdabffa8e0abdf409a075ff70c11dd0..4ac21fce55f35f924779be56bfac6d662d53e22c 100644
--- a/router/java/src/net/i2p/router/RouterContext.java
+++ b/router/java/src/net/i2p/router/RouterContext.java
@@ -93,6 +93,8 @@ public class RouterContext extends I2PAppContext {
             // or about 2 seconds per buffer - so about 200x faster
             // to fill than to drain - so we don't need too many
             long maxMemory = Runtime.getRuntime().maxMemory();
+            if (maxMemory == Long.MAX_VALUE)
+                maxMemory = 96*1024*1024l;
             long buffs = Math.min(16, Math.max(2, maxMemory / (14 * 1024 * 1024)));
             envProps.setProperty("prng.buffers", "" + buffs);
         }
diff --git a/router/java/src/net/i2p/router/transport/ntcp/NTCPSendFinisher.java b/router/java/src/net/i2p/router/transport/ntcp/NTCPSendFinisher.java
index 24b86fd5b30d17493b34b9e7a0a2208ec039f1e7..630036204d5402a6f0c9c7a339265fc27397a88a 100644
--- a/router/java/src/net/i2p/router/transport/ntcp/NTCPSendFinisher.java
+++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPSendFinisher.java
@@ -34,6 +34,8 @@ class NTCPSendFinisher {
     private static final int THREADS;
     static {
         long maxMemory = Runtime.getRuntime().maxMemory();
+        if (maxMemory == Long.MAX_VALUE)
+            maxMemory = 96*1024*1024l;
         THREADS = (int) Math.max(MIN_THREADS, Math.min(MAX_THREADS, 1 + (maxMemory / (32*1024*1024))));
     }
 
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 62d57810e87fedab50b873093eeecc325d5c4e28..326f659effbf2b8fdf193edb155af88edc86c88a 100644
--- a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
+++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
@@ -491,6 +491,8 @@ public class NTCPTransport extends TransportImpl {
         _pumper.startPumping();
 
         long maxMemory = Runtime.getRuntime().maxMemory();
+        if (maxMemory == Long.MAX_VALUE)
+            maxMemory = 128*1024*1024l;
         int nr, nw;
         if (maxMemory < 32*1024*1024) {
             nr = nw = 1;
diff --git a/router/java/src/net/i2p/router/transport/udp/MessageReceiver.java b/router/java/src/net/i2p/router/transport/udp/MessageReceiver.java
index 4988a06851a463b3b9abd9367c623741e185e96c..dede98ef7dc1c629f2f4ddc7796f54a8f56a66a5 100644
--- a/router/java/src/net/i2p/router/transport/udp/MessageReceiver.java
+++ b/router/java/src/net/i2p/router/transport/udp/MessageReceiver.java
@@ -39,6 +39,8 @@ class MessageReceiver {
         _completeMessages = new LinkedBlockingQueue();
 
         long maxMemory = Runtime.getRuntime().maxMemory();
+        if (maxMemory == Long.MAX_VALUE)
+            maxMemory = 96*1024*1024l;
         if (maxMemory < 32*1024*1024)
             _threadCount = 1;
         else if (maxMemory < 64*1024*1024)
diff --git a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java
index ffbcf48aca0f45287569c75a996b2fd8fb26d5ca..824f4a9285eab2e3a3d65c5e5c4e626621832bfd 100644
--- a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java
+++ b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java
@@ -48,6 +48,8 @@ class PacketHandler {
         _introManager = introManager;
 
         long maxMemory = Runtime.getRuntime().maxMemory();
+        if (maxMemory == Long.MAX_VALUE)
+            maxMemory = 96*1024*1024l;
         int num_handlers;
         if (maxMemory < 32*1024*1024)
             num_handlers = 1;
diff --git a/router/java/src/net/i2p/router/tunnel/TunnelGatewayPumper.java b/router/java/src/net/i2p/router/tunnel/TunnelGatewayPumper.java
index 7f29f5743d09b94aaf127dcba64c73bd030393f4..38c72dfaf842bdb37f583ff1b302912ab1ddb44f 100644
--- a/router/java/src/net/i2p/router/tunnel/TunnelGatewayPumper.java
+++ b/router/java/src/net/i2p/router/tunnel/TunnelGatewayPumper.java
@@ -26,6 +26,8 @@ public class TunnelGatewayPumper implements Runnable {
         _wantsPumping = new LinkedBlockingQueue();
         _stop = false;
         long maxMemory = Runtime.getRuntime().maxMemory();
+        if (maxMemory == Long.MAX_VALUE)
+            maxMemory = 96*1024*1024l;
         _pumpers = (int) Math.max(MIN_PUMPERS, Math.min(MAX_PUMPERS, 1 + (maxMemory / (32*1024*1024))));
         for (int i = 0; i < _pumpers; i++)
             new I2PThread(this, "Tunnel GW pumper " + (i+1) + '/' + _pumpers, true).start();