diff --git a/WHATSNEW b/WHATSNEW index a8b6c9119..52c94397e 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -179,6 +179,10 @@ Other changes: an SSH session providing (local and remote) tunnels. Bugzilla Issue 43083. + * ZipOutputStream has been sped up for certain usage scenarios that + are not used by Ant's family of zip tasks. + Bugzilla report 45396. + Changes from Ant 1.7.0 TO Ant 1.7.1 ============================================= diff --git a/src/main/org/apache/tools/zip/ZipOutputStream.java b/src/main/org/apache/tools/zip/ZipOutputStream.java index 765728540..4b03d005e 100644 --- a/src/main/org/apache/tools/zip/ZipOutputStream.java +++ b/src/main/org/apache/tools/zip/ZipOutputStream.java @@ -58,6 +58,14 @@ public class ZipOutputStream extends FilterOutputStream { private static final int SHORT = 2; private static final int WORD = 4; private static final int BUFFER_SIZE = 512; + /* + * Apparently Deflater.setInput gets slowed down a lot on Sun JVMs + * when it gets handed a really big buffer. See + * https://issues.apache.org/bugzilla/show_bug.cgi?id=45396 + * + * Using a buffer size of 8 kB proved to be a good compromise + */ + private static final int DEFLATER_BLOCK_SIZE = 8192; /** * Compression method for deflated entries. @@ -482,9 +490,21 @@ public class ZipOutputStream extends FilterOutputStream { if (entry.getMethod() == DEFLATED) { if (length > 0) { if (!def.finished()) { - def.setInput(b, offset, length); - while (!def.needsInput()) { - deflate(); + if (length <= DEFLATER_BLOCK_SIZE) { + def.setInput(b, offset, length); + deflateUntilInputIsNeeded(); + } else { + final int fullblocks = length / DEFLATER_BLOCK_SIZE; + for (int i = 0; i < fullblocks; i++) { + def.setInput(b, offset + i * DEFLATER_BLOCK_SIZE, + DEFLATER_BLOCK_SIZE); + deflateUntilInputIsNeeded(); + } + final int done = fullblocks * DEFLATER_BLOCK_SIZE; + if (done < length) { + def.setInput(b, offset + done, length - done); + deflateUntilInputIsNeeded(); + } } } } @@ -915,4 +935,10 @@ public class ZipOutputStream extends FilterOutputStream { } } + private void deflateUntilInputIsNeeded() throws IOException { + while (!def.needsInput()) { + deflate(); + } + } + }