Skip to content

Commit c80f797

Browse files
Alexei VoitylovRealCLanger
authored andcommitted
8342562: Enhance Deflater operations
Reviewed-by: mbalao Backport-of: 17f7df55fb762488c1054985830ea13840489df2
1 parent bd052e9 commit c80f797

File tree

2 files changed

+39
-9
lines changed

2 files changed

+39
-9
lines changed

src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,26 @@
4040
* @since 1.1
4141
*/
4242
public class DeflaterOutputStream extends FilterOutputStream {
43+
44+
/*
45+
* The default size of the output buffer
46+
*/
47+
static final int DEFAULT_BUF_SIZE = 512;
48+
49+
/*
50+
* When calling Deflater.deflate() with Deflater.SYNC_FLUSH or Deflater.FULL_FLUSH,
51+
* the callers are expected to ensure that the size of the buffer is greater than 6.
52+
* This expectation comes from the underlying zlib library which in its zlib.h
53+
* states:
54+
* "If deflate returns with avail_out == 0, this function must be called again
55+
* with the same value of the flush parameter and more output space (updated
56+
* avail_out), until the flush is complete (deflate returns with non-zero
57+
* avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
58+
* avail_out is greater than six when the flush marker begins, in order to avoid
59+
* repeated flush markers upon calling deflate() again when avail_out == 0."
60+
*/
61+
private static final int SYNC_FLUSH_MIN_BUF_SIZE = 7;
62+
4363
/**
4464
* Compressor for this stream.
4565
*/
@@ -123,7 +143,7 @@ public DeflaterOutputStream(OutputStream out, Deflater def, int size) {
123143
public DeflaterOutputStream(OutputStream out,
124144
Deflater def,
125145
boolean syncFlush) {
126-
this(out, def, 512, syncFlush);
146+
this(out, def, DEFAULT_BUF_SIZE, syncFlush);
127147
}
128148

129149

@@ -138,7 +158,7 @@ public DeflaterOutputStream(OutputStream out,
138158
* @param def the compressor ("deflater")
139159
*/
140160
public DeflaterOutputStream(OutputStream out, Deflater def) {
141-
this(out, def, 512, false);
161+
this(out, def, DEFAULT_BUF_SIZE, false);
142162
}
143163

144164
boolean usesDefaultDeflater = false;
@@ -158,7 +178,7 @@ public DeflaterOutputStream(OutputStream out, Deflater def) {
158178
* @since 1.7
159179
*/
160180
public DeflaterOutputStream(OutputStream out, boolean syncFlush) {
161-
this(out, out != null ? new Deflater() : null, 512, syncFlush);
181+
this(out, out != null ? new Deflater() : null, DEFAULT_BUF_SIZE, syncFlush);
162182
usesDefaultDeflater = true;
163183
}
164184

@@ -181,6 +201,7 @@ public DeflaterOutputStream(OutputStream out) {
181201
* @param b the byte to be written
182202
* @throws IOException if an I/O error has occurred
183203
*/
204+
@Override
184205
public void write(int b) throws IOException {
185206
byte[] buf = new byte[1];
186207
buf[0] = (byte)(b & 0xff);
@@ -195,6 +216,7 @@ public void write(int b) throws IOException {
195216
* @param len the length of the data
196217
* @throws IOException if an I/O error has occurred
197218
*/
219+
@Override
198220
public void write(byte[] b, int off, int len) throws IOException {
199221
if (def.finished()) {
200222
throw new IOException("write beyond end of stream");
@@ -238,6 +260,7 @@ public void finish() throws IOException {
238260
* underlying stream.
239261
* @throws IOException if an I/O error has occurred
240262
*/
263+
@Override
241264
public void close() throws IOException {
242265
if (!closed) {
243266
try {
@@ -277,13 +300,20 @@ protected void deflate() throws IOException {
277300
*
278301
* @since 1.7
279302
*/
303+
@Override
280304
public void flush() throws IOException {
281305
if (syncFlush && !def.finished()) {
282306
int len = 0;
283-
while ((len = def.deflate(buf, 0, buf.length, Deflater.SYNC_FLUSH)) > 0)
284-
{
285-
out.write(buf, 0, len);
286-
if (len < buf.length)
307+
// For SYNC_FLUSH, the Deflater.deflate() expects the callers
308+
// to use a buffer whose length is greater than 6 to avoid
309+
// flush marker (5 bytes) being repeatedly output to the output buffer
310+
// every time it is invoked.
311+
final byte[] flushBuf = buf.length < SYNC_FLUSH_MIN_BUF_SIZE
312+
? new byte[DEFAULT_BUF_SIZE]
313+
: buf;
314+
while ((len = def.deflate(flushBuf, 0, flushBuf.length, Deflater.SYNC_FLUSH)) > 0) {
315+
out.write(flushBuf, 0, len);
316+
if (len < flushBuf.length)
287317
break;
288318
}
289319
}

src/java.base/share/classes/java/util/zip/GZIPOutputStream.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public GZIPOutputStream(OutputStream out, int size, boolean syncFlush)
109109
* @throws IOException If an I/O error has occurred.
110110
*/
111111
public GZIPOutputStream(OutputStream out) throws IOException {
112-
this(out, 512, false);
112+
this(out, DeflaterOutputStream.DEFAULT_BUF_SIZE, false);
113113
}
114114

115115
/**
@@ -131,7 +131,7 @@ public GZIPOutputStream(OutputStream out) throws IOException {
131131
public GZIPOutputStream(OutputStream out, boolean syncFlush)
132132
throws IOException
133133
{
134-
this(out, 512, syncFlush);
134+
this(out, DeflaterOutputStream.DEFAULT_BUF_SIZE, syncFlush);
135135
}
136136

137137
/**

0 commit comments

Comments
 (0)