diff --git a/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketFull.java b/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketFull.java
index abca9b82fc79f184ee8b507f6369f511bf4012aa..95d551d7382b655d096af9381df713eab4532f1d 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketFull.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketFull.java
@@ -4,29 +4,41 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.channels.SelectableChannel;
+import java.util.concurrent.atomic.AtomicBoolean;
 
+import net.i2p.I2PAppContext;
 import net.i2p.client.I2PSession;
 import net.i2p.data.Destination;
+import net.i2p.util.Log;
 
 /**
  * Bridge between the full streaming lib and the I2PSocket API
  *
  */
 class I2PSocketFull implements I2PSocket {
-    private Connection _connection;
-    private Destination _remotePeer;
-    private Destination _localPeer;
+    private final Log log;
+    private volatile Connection _connection;
+    private final Destination _remotePeer;
+    private final Destination _localPeer;
     private volatile MessageChannel _channel;
+    private final AtomicBoolean _closed = new AtomicBoolean(false);
     
-    public I2PSocketFull(Connection con) {
+    public I2PSocketFull(Connection con, I2PAppContext context) {
+        log = context.logManager().getLog(I2PSocketFull.class);
         _connection = con;
         if (con != null) {
             _remotePeer = con.getRemotePeer();
             _localPeer = con.getSession().getMyDestination();
-        }
+        } else
+            _remotePeer = _localPeer = null;
     }
     
     public void close() throws IOException {
+        if (!_closed.compareAndSet(false,true)) {
+            // log a trace to find out why
+            LogUtil.logCloseLoop(log, "I2PSocket",_localPeer,"-->",_remotePeer,_connection);
+            return;
+        }
         Connection c = _connection;
         if (c == null) return;
         if (c.getIsConnected()) {
diff --git a/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java b/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java
index 83f170d84f8f5e3d8ba92342d75e4e839931a8d3..a60888f2cc6d74a8d9152b29aad559436d4c4072 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java
@@ -316,10 +316,7 @@ public class I2PSocketManagerFull implements I2PSocketManager {
     public void destroySocketManager() {
         if (!_isDestroyed.compareAndSet(false,true)) {
             // shouldn't happen, log a stack trace to find out why it happened
-            if (_log.shouldLog(Log.WARN)) {
-                String log = "over-destroying manager "+getName();
-                _log.log(Log.WARN,log,new Exception("check stack trace"));
-            }
+            LogUtil.logCloseLoop(_log, "I2PSocketManager", getName());
             return;
         }
         _connectionManager.setAllowIncomingConnections(false);
diff --git a/apps/streaming/java/src/net/i2p/client/streaming/LogUtil.java b/apps/streaming/java/src/net/i2p/client/streaming/LogUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..27d4752700a4a8b2b028d00e91dc4245c01b7e9e
--- /dev/null
+++ b/apps/streaming/java/src/net/i2p/client/streaming/LogUtil.java
@@ -0,0 +1,37 @@
+package net.i2p.client.streaming;
+
+import net.i2p.util.Log;
+
+class LogUtil {
+    private LogUtil() {}
+    
+    /**
+     * logs a loop when closing a resource with level WARN
+     * @param desc vararg description
+     * @param log logger for the class we're intersted in
+     */
+    static void logCloseLoop(Log log, Object... desc) {
+        logCloseLoop(log, Log.WARN, desc);
+    }
+    
+    /**
+     * Logs a close loop when closing a resource
+     * @param desc vararg description of the resource
+     * @param log logger to use
+     * @param level level at which to log
+     */
+    static void logCloseLoop(Log log, int level, Object... desc) {
+        if (!log.shouldLog(level)) 
+            return;
+        
+        // catenate all toString()s
+        String descString = "close() loop in";
+        for (Object o : desc) {
+            descString += " ";
+            descString += String.valueOf(o);
+        }
+        
+        Exception e = new Exception("check stack trace");
+        log.log(level,descString,e);
+    }
+}