Repository: aurora Updated Branches: refs/heads/master 2b48f2216 -> c76cfcc5f
Always close Deflater/Inflater streams Closing Deflater/Inflater streams explicitly frees their native memory instantly. Otherwise, the memory will only be freed once the object finalizer runs. I got the idea from this article http://www.evanjones.ca/java-native-leak-bug.html. Unfortunately, we cannot use the Java close-with-resource feature, as `TTransport` in our current Thrift version does not implement `Closable`. Reviewed at https://reviews.apache.org/r/43567/ Project: http://git-wip-us.apache.org/repos/asf/aurora/repo Commit: http://git-wip-us.apache.org/repos/asf/aurora/commit/c76cfcc5 Tree: http://git-wip-us.apache.org/repos/asf/aurora/tree/c76cfcc5 Diff: http://git-wip-us.apache.org/repos/asf/aurora/diff/c76cfcc5 Branch: refs/heads/master Commit: c76cfcc5f0bf9013f39593b1ac00cd44efc79c40 Parents: 2b48f22 Author: Stephan Erb <s...@apache.org> Authored: Sun Feb 14 23:34:10 2016 +0100 Committer: Stephan Erb <step...@dev.static-void.de> Committed: Sun Feb 14 23:34:10 2016 +0100 ---------------------------------------------------------------------- .../apache/aurora/codec/ThriftBinaryCodec.java | 30 +++++++++++--------- 1 file changed, 17 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/aurora/blob/c76cfcc5/src/main/java/org/apache/aurora/codec/ThriftBinaryCodec.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/aurora/codec/ThriftBinaryCodec.java b/src/main/java/org/apache/aurora/codec/ThriftBinaryCodec.java index 6b65c0f..3c12532 100644 --- a/src/main/java/org/apache/aurora/codec/ThriftBinaryCodec.java +++ b/src/main/java/org/apache/aurora/codec/ThriftBinaryCodec.java @@ -145,24 +145,26 @@ public final class ThriftBinaryCodec { public static byte[] deflateNonNull(TBase<?, ?> tBase) throws CodingException { requireNonNull(tBase); + // NOTE: Buffering is needed here for performance. + // There are actually 2 buffers in play here - the BufferedOutputStream prevents thrift from + // causing a call to deflate() on every encoded primitive. The DeflaterOutputStream buffer + // allows the underlying Deflater to operate on a larger chunk at a time without stopping to + // copy the intermediate compressed output to outBytes. + // See http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4986239 ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); + TTransport transport = new TIOStreamTransport( + new BufferedOutputStream( + new DeflaterOutputStream(outBytes, new Deflater(DEFLATE_LEVEL), DEFLATER_BUFFER_SIZE), + DEFLATER_BUFFER_SIZE)); try { - // NOTE: Buffering is needed here for performance. - // There are actually 2 buffers in play here - the BufferedOutputStream prevents thrift from - // causing a call to deflate() on every encoded primitive. The DeflaterOutputStream buffer - // allows the underlying Deflater to operate on a larger chunk at a time without stopping to - // copy the intermediate compressed output to outBytes. - // See http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4986239 - TTransport transport = new TIOStreamTransport( - new BufferedOutputStream( - new DeflaterOutputStream(outBytes, new Deflater(DEFLATE_LEVEL), DEFLATER_BUFFER_SIZE), - DEFLATER_BUFFER_SIZE)); TProtocol protocol = PROTOCOL_FACTORY.getProtocol(transport); tBase.write(protocol); - transport.close(); + transport.close(); // calls finish() on the underlying stream, completing the compression return outBytes.toByteArray(); } catch (TException e) { throw new CodingException("Failed to serialize: " + tBase, e); + } finally { + transport.close(); } } @@ -181,14 +183,16 @@ public final class ThriftBinaryCodec { requireNonNull(buffer); T tBase = newInstance(clazz); - try { - TTransport transport = new TIOStreamTransport( + TTransport transport = new TIOStreamTransport( new InflaterInputStream(new ByteArrayInputStream(buffer))); + try { TProtocol protocol = PROTOCOL_FACTORY.getProtocol(transport); tBase.read(protocol); return tBase; } catch (TException e) { throw new CodingException("Failed to deserialize: " + e, e); + } finally { + transport.close(); } }