Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoakim Erdfelt2016-02-04 13:03:45 -0500
committerJoakim Erdfelt2016-02-04 13:03:45 -0500
commitcfe823a7d6edab044d4a1751dd3dfa2dda89c3e6 (patch)
tree398d3427419d00e51cde01d21ebe100d11e22d60
parent980ab316cad2a95d2b4ac73882ceb2a3bb147b09 (diff)
downloadorg.eclipse.jetty.project-cfe823a7d6edab044d4a1751dd3dfa2dda89c3e6.tar.gz
org.eclipse.jetty.project-cfe823a7d6edab044d4a1751dd3dfa2dda89c3e6.tar.xz
org.eclipse.jetty.project-cfe823a7d6edab044d4a1751dd3dfa2dda89c3e6.zip
487197 - Deflater/Inflater memory leak with WebSocket permessage-deflate extension
+ CompressExtension implementations are now part of the Jetty LifeCycle + Deflater and Inflater implementations are only instantiated when needed. + CompressExtension.doStop() LifeCycle will call .end() on instantiated Deflater and Inflater implementations
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/AbstractExtension.java12
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/ExtensionStack.java6
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java33
3 files changed, 42 insertions, 9 deletions
diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/AbstractExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/AbstractExtension.java
index 58e8c90db6..f1abf1e49f 100644
--- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/AbstractExtension.java
+++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/AbstractExtension.java
@@ -23,7 +23,9 @@ import java.io.IOException;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
+import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
+import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.BatchMode;
@@ -38,7 +40,7 @@ import org.eclipse.jetty.websocket.common.LogicalConnection;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
@ManagedObject("Abstract Extension")
-public abstract class AbstractExtension extends ContainerLifeCycle implements Extension
+public abstract class AbstractExtension extends AbstractLifeCycle implements Dumpable, Extension
{
private final Logger log;
private WebSocketPolicy policy;
@@ -52,11 +54,15 @@ public abstract class AbstractExtension extends ContainerLifeCycle implements Ex
{
log = Log.getLogger(this.getClass());
}
-
+
@Override
+ public String dump()
+ {
+ return ContainerLifeCycle.dump(this);
+ }
+
public void dump(Appendable out, String indent) throws IOException
{
- super.dump(out, indent);
// incoming
dumpWithHeading(out, indent, "incoming", this.nextIncoming);
dumpWithHeading(out, indent, "outgoing", this.nextOutgoing);
diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/ExtensionStack.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/ExtensionStack.java
index 720e98146b..2cde3a5ab3 100644
--- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/ExtensionStack.java
+++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/ExtensionStack.java
@@ -29,6 +29,7 @@ import org.eclipse.jetty.util.IteratingCallback;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
+import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.BatchMode;
@@ -89,6 +90,11 @@ public class ExtensionStack extends ContainerLifeCycle implements IncomingFrames
Extension ext = exts.next();
ext.setNextOutgoingFrames(nextOutgoing);
nextOutgoing = ext;
+
+ if (ext instanceof LifeCycle)
+ {
+ addBean(ext,true);
+ }
}
// Connect incomings
diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java
index ac32ad6d72..f7325c73c3 100644
--- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java
+++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java
@@ -74,28 +74,34 @@ public abstract class CompressExtension extends AbstractExtension
private final Queue<FrameEntry> entries = new ConcurrentArrayQueue<>();
private final IteratingCallback flusher = new Flusher();
- private final Deflater deflater;
- private final Inflater inflater;
+ private Deflater deflaterImpl;
+ private Inflater inflaterImpl;
protected AtomicInteger decompressCount = new AtomicInteger(0);
private int tailDrop = TAIL_DROP_NEVER;
private int rsvUse = RSV_USE_ALWAYS;
protected CompressExtension()
{
- deflater = new Deflater(Deflater.DEFAULT_COMPRESSION,NOWRAP);
- inflater = new Inflater(NOWRAP);
tailDrop = getTailDropMode();
rsvUse = getRsvUseMode();
}
public Deflater getDeflater()
{
- return deflater;
+ if (deflaterImpl == null)
+ {
+ deflaterImpl = new Deflater(Deflater.DEFAULT_COMPRESSION,NOWRAP);
+ }
+ return deflaterImpl;
}
public Inflater getInflater()
{
- return inflater;
+ if (inflaterImpl == null)
+ {
+ inflaterImpl = new Inflater(NOWRAP);
+ }
+ return inflaterImpl;
}
/**
@@ -155,6 +161,8 @@ public abstract class CompressExtension extends AbstractExtension
}
byte[] output = new byte[DECOMPRESS_BUF_SIZE];
+ Inflater inflater = getInflater();
+
while(buf.hasRemaining() && inflater.needsInput())
{
if (!supplyInput(inflater,buf))
@@ -346,6 +354,17 @@ public abstract class CompressExtension extends AbstractExtension
}
return true;
}
+
+ @Override
+ protected void doStop() throws Exception
+ {
+ LOG.info("doStop()");
+ if(deflaterImpl != null)
+ deflaterImpl.end();
+ if(inflaterImpl != null)
+ inflaterImpl.end();
+ super.doStop();
+ }
@Override
public String toString()
@@ -429,6 +448,8 @@ public abstract class CompressExtension extends AbstractExtension
LOG.debug("Compressing {}: {} bytes in {} bytes chunk",entry,remaining,outputLength);
boolean needsCompress = true;
+
+ Deflater deflater = getDeflater();
if (deflater.needsInput() && !supplyInput(deflater,data))
{

Back to the top