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