forked from I2P_Developers/i2p.i2p
Util: Fix memory leak in compressor (ticket #2471)
This commit is contained in:
@ -168,6 +168,15 @@ public class ResettableGZIPInputStream extends InflaterInputStream {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls super.close(). May not be reused after this.
|
||||
* @since 0.9.40
|
||||
*/
|
||||
public void destroy() throws IOException {
|
||||
close();
|
||||
super.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Does NOT call super.close(), as it cannot be reused if we do that.
|
||||
* Broken before 0.9.20.
|
||||
|
@ -18,6 +18,7 @@ import java.util.zip.DeflaterOutputStream;
|
||||
public class ResettableGZIPOutputStream extends DeflaterOutputStream {
|
||||
/** has the header been written out yet? */
|
||||
private boolean _headerWritten;
|
||||
private boolean _footerWritten;
|
||||
/** how much data is in the uncompressed stream? */
|
||||
private long _writtenSize;
|
||||
private final CRC32 _crc32;
|
||||
@ -39,6 +40,7 @@ public class ResettableGZIPOutputStream extends DeflaterOutputStream {
|
||||
_crc32.reset();
|
||||
_writtenSize = 0;
|
||||
_headerWritten = false;
|
||||
_footerWritten = false;
|
||||
}
|
||||
|
||||
private static final byte[] HEADER = new byte[] {
|
||||
@ -61,6 +63,7 @@ public class ResettableGZIPOutputStream extends DeflaterOutputStream {
|
||||
}
|
||||
|
||||
private void writeFooter() throws IOException {
|
||||
if (_footerWritten) return;
|
||||
// damn RFC writing their bytes backwards...
|
||||
long crcVal = _crc32.getValue();
|
||||
out.write((int)(crcVal & 0xFF));
|
||||
@ -83,6 +86,16 @@ public class ResettableGZIPOutputStream extends DeflaterOutputStream {
|
||||
System.out.print( Long.toHexString((int)((sizeVal >>> 24) & 0xFF)));
|
||||
System.out.println();
|
||||
}
|
||||
_footerWritten = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls super.close(). May not be reused after this.
|
||||
* @since 0.9.40
|
||||
*/
|
||||
public void destroy() throws IOException {
|
||||
def.end();
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -90,6 +103,7 @@ public class ResettableGZIPOutputStream extends DeflaterOutputStream {
|
||||
finish();
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() throws IOException {
|
||||
ensureHeaderIsWritten();
|
||||
@ -104,10 +118,12 @@ public class ResettableGZIPOutputStream extends DeflaterOutputStream {
|
||||
_writtenSize++;
|
||||
super.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte buf[]) throws IOException {
|
||||
write(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte buf[], int off, int len) throws IOException {
|
||||
ensureHeaderIsWritten();
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.i2p.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
/**
|
||||
@ -32,13 +33,21 @@ public class ReusableGZIPInputStream extends ResettableGZIPInputStream {
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release an instance back into the cache (this will reset the
|
||||
* state)
|
||||
*/
|
||||
public static void release(ReusableGZIPInputStream released) {
|
||||
if (ENABLE_CACHING)
|
||||
_available.offer(released);
|
||||
boolean cached;
|
||||
if (ENABLE_CACHING) {
|
||||
cached = _available.offer(released);
|
||||
} else {
|
||||
cached = false;
|
||||
}
|
||||
if (!cached) {
|
||||
try { released.destroy(); } catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
|
||||
private ReusableGZIPInputStream() { super(); }
|
||||
|
@ -2,6 +2,7 @@ package net.i2p.util;
|
||||
|
||||
//import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
@ -50,9 +51,16 @@ public class ReusableGZIPOutputStream extends ResettableGZIPOutputStream {
|
||||
* state)
|
||||
*/
|
||||
public static void release(ReusableGZIPOutputStream out) {
|
||||
out.reset();
|
||||
if (ENABLE_CACHING)
|
||||
_available.offer(out);
|
||||
boolean cached;
|
||||
if (ENABLE_CACHING) {
|
||||
out.reset();
|
||||
cached = _available.offer(out);
|
||||
} else {
|
||||
cached = false;
|
||||
}
|
||||
if (!cached) {
|
||||
try { out.destroy(); } catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
|
||||
private final ByteArrayOutputStream _buffer;
|
||||
|
Reference in New Issue
Block a user