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
This commit is contained in:
parent
980ab316ca
commit
cfe823a7d6
|
@ -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;
|
||||
|
@ -54,9 +56,13 @@ public abstract class AbstractExtension extends ContainerLifeCycle implements Ex
|
|||
}
|
||||
|
||||
@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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
@ -347,6 +355,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()
|
||||
{
|
||||
|
@ -430,6 +449,8 @@ public abstract class CompressExtension extends AbstractExtension
|
|||
|
||||
boolean needsCompress = true;
|
||||
|
||||
Deflater deflater = getDeflater();
|
||||
|
||||
if (deflater.needsInput() && !supplyInput(deflater,data))
|
||||
{
|
||||
// no input supplied
|
||||
|
|
Loading…
Reference in New Issue