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 94ec5532c1fbb12977b7c64e9d94d6b98ac4c746..c7495131f3d1609cc31840fb67e892298245801f 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/Connection.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/Connection.java
@@ -333,7 +333,8 @@ public class Connection {
             ResendPacketEvent rpe = new ResendPacketEvent(packet, timeout);
         }
 
-        _context.statManager().getStatLog().addData(Packet.toId(_sendStreamId), "stream.rtt", _options.getRTT(), _options.getWindowSize());
+        // warning, getStatLog() can be null
+        //_context.statManager().getStatLog().addData(Packet.toId(_sendStreamId), "stream.rtt", _options.getRTT(), _options.getWindowSize());
         
         _lastSendTime = _context.clock().now();
         _outboundQueue.enqueue(packet);        
diff --git a/core/java/src/net/i2p/stat/BufferedStatLog.java b/core/java/src/net/i2p/stat/BufferedStatLog.java
index d863ad59a17fda521c77cc4eec3fe6eece6b6324..4703a257605103b26aa756b73eb62a36a0d9a661 100644
--- a/core/java/src/net/i2p/stat/BufferedStatLog.java
+++ b/core/java/src/net/i2p/stat/BufferedStatLog.java
@@ -15,7 +15,8 @@ import net.i2p.util.I2PThread;
 import net.i2p.util.Log;
 
 /**
- * 
+ * Note - if no filter is defined in stat.logFilters at startup, this class will not
+ * be instantiated - see StatManager.
  */
 public class BufferedStatLog implements StatLog {
     private I2PAppContext _context;
@@ -46,7 +47,7 @@ public class BufferedStatLog implements StatLog {
         _lastWrite = _events.length-1;
         _statFilters = new ArrayList(10);
         _flushFrequency = 500;
-        _filtersSpecified = false;
+        updateFilters();
         I2PThread writer = new I2PThread(new StatLogWriter(), "StatLogWriter");
         writer.setDaemon(true);
         writer.start();
@@ -93,10 +94,7 @@ public class BufferedStatLog implements StatLog {
                     _statFilters.clear();
                     while (tok.hasMoreTokens())
                         _statFilters.add(tok.nextToken().trim());
-                    if (_statFilters.size() > 0)
-                        _filtersSpecified = true;
-                    else
-                        _filtersSpecified = false;
+                    _filtersSpecified = _statFilters.size() > 0;
                 }
             }
             _lastFilters = val;
@@ -107,9 +105,7 @@ public class BufferedStatLog implements StatLog {
             }
         }
         
-        String filename = _context.getProperty(StatManager.PROP_STAT_FILE);
-        if (filename == null)
-            filename = StatManager.DEFAULT_STAT_FILE;
+        String filename = _context.getProperty(StatManager.PROP_STAT_FILE, StatManager.DEFAULT_STAT_FILE);
         File foo = new File(filename);
         if (!foo.isAbsolute())
             filename = (new File(_context.getRouterDir(), filename)).getAbsolutePath();
diff --git a/core/java/src/net/i2p/stat/StatManager.java b/core/java/src/net/i2p/stat/StatManager.java
index fbdbd453f1a4120c9af41900d35b1526c453f3ad..9670048d300ca0ebce9c428482329def41104d3d 100644
--- a/core/java/src/net/i2p/stat/StatManager.java
+++ b/core/java/src/net/i2p/stat/StatManager.java
@@ -25,11 +25,17 @@ public class StatManager {
     private I2PAppContext _context;
 
     /** stat name to FrequencyStat */
-    private final Map _frequencyStats;
+    private final Map<String, FrequencyStat> _frequencyStats;
     /** stat name to RateStat */
-    private final Map _rateStats;
+    private final Map<String, RateStat> _rateStats;
+    /** may be null */
     private StatLog _statLog;
 
+    /**
+     *  Comma-separated stats or * for all.
+     *  This property must be set at startup, or
+     *  logging is disabled.
+     */
     public static final String PROP_STAT_FILTER = "stat.logFilters";
     public static final String PROP_STAT_FILE = "stat.logFile";
     public static final String DEFAULT_STAT_FILE = "stats.log";
@@ -65,17 +71,19 @@ public class StatManager {
     public StatManager(I2PAppContext context) {
         _log = context.logManager().getLog(StatManager.class);
         _context = context;
-        _frequencyStats = Collections.synchronizedMap(new HashMap(128));
+        _frequencyStats = Collections.synchronizedMap(new HashMap(8));
         _rateStats = new HashMap(128); // synchronized only on add //Collections.synchronizedMap(new HashMap(128));
-        _statLog = new BufferedStatLog(context);
+        if (getStatFilter() != null)
+            _statLog = new BufferedStatLog(context);
     }
     
+    /** may be null */
     public StatLog getStatLog() { return _statLog; }
     public void setStatLog(StatLog log) { 
         _statLog = log; 
         synchronized (_rateStats) {
-            for (Iterator iter = _rateStats.values().iterator(); iter.hasNext(); ) {
-                RateStat rs = (RateStat)iter.next();
+            for (Iterator<RateStat> iter = _rateStats.values().iterator(); iter.hasNext(); ) {
+                RateStat rs = iter.next();
                 rs.setStatLog(log);
             }
         }
@@ -122,28 +130,28 @@ public class StatManager {
 
     /** update the given frequency statistic, taking note that an event occurred (and recalculating all frequencies) */
     public void updateFrequency(String name) {
-        FrequencyStat freq = (FrequencyStat) _frequencyStats.get(name);
+        FrequencyStat freq = _frequencyStats.get(name);
         if (freq != null) freq.eventOccurred();
     }
 
     /** update the given rate statistic, taking note that the given data point was received (and recalculating all rates) */
     public void addRateData(String name, long data, long eventDuration) {
-        RateStat stat = (RateStat) _rateStats.get(name); // unsynchronized
+        RateStat stat = _rateStats.get(name); // unsynchronized
         if (stat != null) stat.addData(data, eventDuration);
     }
 
     public void coalesceStats() {
         synchronized (_frequencyStats) {
-            for (Iterator iter = _frequencyStats.values().iterator(); iter.hasNext();) {
-                FrequencyStat stat = (FrequencyStat)iter.next();
+            for (Iterator<FrequencyStat> iter = _frequencyStats.values().iterator(); iter.hasNext();) {
+                FrequencyStat stat = iter.next();
                 if (stat != null) {
                     stat.coalesceStats();
                 }
             }
         }
         synchronized (_rateStats) {
-            for (Iterator iter = _rateStats.values().iterator(); iter.hasNext();) {
-                RateStat stat = (RateStat)iter.next();
+            for (Iterator<RateStat> iter = _rateStats.values().iterator(); iter.hasNext();) {
+                RateStat stat = iter.next();
                 if (stat != null) {
                     stat.coalesceStats();
                 }
@@ -152,18 +160,18 @@ public class StatManager {
     }
 
     public FrequencyStat getFrequency(String name) {
-        return (FrequencyStat) _frequencyStats.get(name);
+        return _frequencyStats.get(name);
     }
 
     public RateStat getRate(String name) {
-        return (RateStat) _rateStats.get(name);
+        return _rateStats.get(name);
     }
 
-    public Set getFrequencyNames() {
+    public Set<String> getFrequencyNames() {
         return new HashSet(_frequencyStats.keySet());
     }
 
-    public Set getRateNames() {
+    public Set<String> getRateNames() {
         return new HashSet(_rateStats.keySet());
     }
 
@@ -180,14 +188,14 @@ public class StatManager {
     /** Group name (String) to a Set of stat names, ordered alphabetically */
     public Map getStatsByGroup() {
         Map groups = new TreeMap(Collator.getInstance());
-        for (Iterator iter = _frequencyStats.values().iterator(); iter.hasNext();) {
-            FrequencyStat stat = (FrequencyStat) iter.next();
+        for (Iterator<FrequencyStat> iter = _frequencyStats.values().iterator(); iter.hasNext();) {
+            FrequencyStat stat = iter.next();
             if (!groups.containsKey(stat.getGroupName())) groups.put(stat.getGroupName(), new TreeSet());
             Set names = (Set) groups.get(stat.getGroupName());
             names.add(stat.getName());
         }
-        for (Iterator iter = _rateStats.values().iterator(); iter.hasNext();) {
-            RateStat stat = (RateStat) iter.next();
+        for (Iterator<RateStat> iter = _rateStats.values().iterator(); iter.hasNext();) {
+            RateStat stat = iter.next();
             if (!groups.containsKey(stat.getGroupName())) groups.put(stat.getGroupName(), new TreeSet());
             Set names = (Set) groups.get(stat.getGroupName());
             names.add(stat.getName());
@@ -198,8 +206,10 @@ public class StatManager {
     public String getStatFilter() { return _context.getProperty(PROP_STAT_FILTER); }
     public String getStatFile() { return _context.getProperty(PROP_STAT_FILE, DEFAULT_STAT_FILE); }
 
-    // Save memory by not creating stats unless they are required for router operation
-    // Return true if the stat should be ignored.
+    /**
+     * Save memory by not creating stats unless they are required for router operation
+     * @return true if the stat should be ignored.
+     */
     public boolean ignoreStat(String statName) {
         if (_context.getProperty(PROP_STAT_FULL, DEFAULT_STAT_FULL).equalsIgnoreCase("true"))
             return false;
diff --git a/core/java/src/net/i2p/stat/SimpleStatDumper.java b/core/java/test/net/i2p/stat/SimpleStatDumper.java
similarity index 100%
rename from core/java/src/net/i2p/stat/SimpleStatDumper.java
rename to core/java/test/net/i2p/stat/SimpleStatDumper.java
diff --git a/core/java/src/net/i2p/stat/StatLogSplitter.java b/core/java/test/net/i2p/stat/StatLogSplitter.java
similarity index 100%
rename from core/java/src/net/i2p/stat/StatLogSplitter.java
rename to core/java/test/net/i2p/stat/StatLogSplitter.java
diff --git a/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java b/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java
index 11d36419161077e7965b87abcfee4576de4d1d5e..75c73dd34bcadf12b9601c491ccb5d679fe9c15f 100644
--- a/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java
+++ b/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java
@@ -303,12 +303,13 @@ public class FIFOBandwidthLimiter {
             else
                 _recvBps = (0.9f)*_recvBps + (0.1f)*((float)recv*1000)/(float)time;
 
-            if (_log.shouldLog(Log.WARN)) {
+            // warning, getStatLog() can be null
+            //if (_log.shouldLog(Log.WARN)) {
                 //if (_log.shouldLog(Log.INFO))
                 //    _log.info("BW: time = " + time + " sent: " + _sendBps + " recv: " + _recvBps);
-                _context.statManager().getStatLog().addData("bw", "bw.sendBps1s", (long)_sendBps, sent);
-                _context.statManager().getStatLog().addData("bw", "bw.recvBps1s", (long)_recvBps, recv);
-            }
+            //    _context.statManager().getStatLog().addData("bw", "bw.sendBps1s", (long)_sendBps, sent);
+            //    _context.statManager().getStatLog().addData("bw", "bw.recvBps1s", (long)_recvBps, recv);
+            //}
 
             // Maintain an approximate average with a 15-second halflife
             // Weights (0.955 and 0.045) are tuned so that transition between two values (e.g. 0..10)
@@ -323,12 +324,13 @@ public class FIFOBandwidthLimiter {
             //else
                 _recvBps15s = (0.955f)*_recvBps15s + (0.045f)*((float)recv*1000)/(float)time;
 
-            if (_log.shouldLog(Log.WARN)) {
-                if (_log.shouldLog(Log.DEBUG))
-                    _log.debug("BW15: time = " + time + " sent: " + _sendBps + " recv: " + _recvBps);
-                _context.statManager().getStatLog().addData("bw", "bw.sendBps15s", (long)_sendBps15s, sent);
-                _context.statManager().getStatLog().addData("bw", "bw.recvBps15s", (long)_recvBps15s, recv);
-            }
+            // warning, getStatLog() can be null
+            //if (_log.shouldLog(Log.WARN)) {
+            //    if (_log.shouldLog(Log.DEBUG))
+            //        _log.debug("BW15: time = " + time + " sent: " + _sendBps + " recv: " + _recvBps);
+            //    _context.statManager().getStatLog().addData("bw", "bw.sendBps15s", (long)_sendBps15s, sent);
+            //    _context.statManager().getStatLog().addData("bw", "bw.recvBps15s", (long)_recvBps15s, recv);
+            //}
         }
     }
     
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 14dfced396ccbe7d0afad19161158e4e03675d63..633b924219e544ad917fc56a69826315554144e8 100644
--- a/router/java/src/net/i2p/router/transport/udp/UDPFlooder.java
+++ b/router/java/src/net/i2p/router/transport/udp/UDPFlooder.java
@@ -90,7 +90,8 @@ class UDPFlooder implements Runnable {
                         if (to == null)
                             continue;
                         msg.setTarget(to);
-                        _context.statManager().getStatLog().addData(peer.getRemotePeer().toBase64().substring(0,6), "udp.floodDataSent", 1, 0);
+                        // warning, getStatLog() can be null
+                        //_context.statManager().getStatLog().addData(peer.getRemotePeer().toBase64().substring(0,6), "udp.floodDataSent", 1, 0);
 
                         _transport.send(msg);
                     } else {