From eeb03766b61f70413088962ea978d8a9f638bab7 Mon Sep 17 00:00:00 2001 From: zzz Date: Fri, 17 Jun 2011 00:09:05 +0000 Subject: [PATCH] client executor kill take 2 --- .../i2ptunnel/HTTPResponseOutputStream.java | 2 +- .../i2p/i2ptunnel/I2PTunnelClientBase.java | 35 +++++++++++++++---- .../i2p/i2ptunnel/TunnelControllerGroup.java | 4 +++ 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/HTTPResponseOutputStream.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/HTTPResponseOutputStream.java index 7fc808643..8ede20332 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/HTTPResponseOutputStream.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/HTTPResponseOutputStream.java @@ -233,7 +233,7 @@ class HTTPResponseOutputStream extends FilterOutputStream { // there after the accept(). // Overridden in I2PTunnelHTTPServer, where it does not use the client pool. try { - I2PTunnelClientBase._executor.execute(new Pusher(pi, out)); + I2PTunnelClientBase.getClientExecutor().execute(new Pusher(pi, out)); } catch (RejectedExecutionException ree) { // shouldn't happen throw ree; diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java index ed799bf6b..d54c48294 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java @@ -83,11 +83,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna * Extending classes may use it for other purposes. * Not for use by servers, as there is no limit on threads. */ - static final ThreadPoolExecutor _executor; + private static ThreadPoolExecutor _executor; private static int _executorThreadCount; - static { - _executor = new CustomThreadPoolExecutor(); - } public I2PTunnelClientBase(int localPort, Logging l, I2PSocketManager sktMgr, I2PTunnel tunnel, EventDispatcher notifyThis, long clientId ) @@ -107,6 +104,10 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna _context.statManager().createRateStat("i2ptunnel.client.buildRunTime", "How long it takes to run a queued socket into an i2ptunnel runner?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); _log = _context.logManager().getLog(getClass()); + synchronized (I2PTunnelClientBase.class) { + if (_executor == null) + _executor = new CustomThreadPoolExecutor(); + } Thread t = new I2PAppThread(this, "Client " + tunnel.listenHost + ':' + localPort); listenerReady = false; t.start(); @@ -551,6 +552,30 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna } } + /** + * @return may be null if no class has been instantiated + * @since 0.8.8 + */ + static ThreadPoolExecutor getClientExecutor() { + return _executor; + } + + /** + * @since 0.8.8 + */ + static void killClientExecutor() { + synchronized (I2PTunnelClientBase.class) { + if (_executor == null) { + _executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); + _executor.shutdownNow(); + _executor = null; + } + // kill the shared client, so that on restart in android + // we won't latch onto the old one + socketManager = null; + } + } + /** * Manage the connection just opened on the specified socket * @@ -635,8 +660,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna } //l.log("Client closed."); } - _executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); - _executor.shutdownNow(); return true; } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelControllerGroup.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelControllerGroup.java index af8166a9d..600464f87 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelControllerGroup.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelControllerGroup.java @@ -86,6 +86,9 @@ public class TunnelControllerGroup { /** * Warning - destroys the singleton! * Caller must root a new context before calling instance() or main() again. + * Agressively kill and null everything to reduce memory usage in the JVM + * after stopping, and to recognize what must be reinitialized on restart (Android) + * * @since 0.8.8 */ public static void shutdown() { @@ -95,6 +98,7 @@ public class TunnelControllerGroup { _instance._log = null; _instance = null; } + I2PTunnelClientBase.killClientExecutor(); } /**