Skip to content

Commit 11f9400

Browse files
Aleksei Voitylovgnu-andrew
authored andcommitted
8342562: Enhance Deflater operations
Reviewed-by: yan, mbalao, andrew Backport-of: 185fc0c9163f5f79528ebfc96d01ec76e727fc58
1 parent 2b70822 commit 11f9400

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
@@ -41,6 +41,26 @@
4141
*/
4242
public
4343
class DeflaterOutputStream extends FilterOutputStream {
44+
45+
/*
46+
* The default size of the output buffer
47+
*/
48+
static final int DEFAULT_BUF_SIZE = 512;
49+
50+
/*
51+
* When calling Deflater.deflate() with Deflater.SYNC_FLUSH or Deflater.FULL_FLUSH,
52+
* the callers are expected to ensure that the size of the buffer is greater than 6.
53+
* This expectation comes from the underlying zlib library which in its zlib.h
54+
* states:
55+
* "If deflate returns with avail_out == 0, this function must be called again
56+
* with the same value of the flush parameter and more output space (updated
57+
* avail_out), until the flush is complete (deflate returns with non-zero
58+
* avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
59+
* avail_out is greater than six when the flush marker begins, in order to avoid
60+
* repeated flush markers upon calling deflate() again when avail_out == 0."
61+
*/
62+
private static final int SYNC_FLUSH_MIN_BUF_SIZE = 7;
63+
4464
/**
4565
* Compressor for this stream.
4666
*/
@@ -124,7 +144,7 @@ public DeflaterOutputStream(OutputStream out, Deflater def, int size) {
124144
public DeflaterOutputStream(OutputStream out,
125145
Deflater def,
126146
boolean syncFlush) {
127-
this(out, def, 512, syncFlush);
147+
this(out, def, DEFAULT_BUF_SIZE, syncFlush);
128148
}
129149

130150

@@ -139,7 +159,7 @@ public DeflaterOutputStream(OutputStream out,
139159
* @param def the compressor ("deflater")
140160
*/
141161
public DeflaterOutputStream(OutputStream out, Deflater def) {
142-
this(out, def, 512, false);
162+
this(out, def, DEFAULT_BUF_SIZE, false);
143163
}
144164

145165
boolean usesDefaultDeflater = false;
@@ -159,7 +179,7 @@ public DeflaterOutputStream(OutputStream out, Deflater def) {
159179
* @since 1.7
160180
*/
161181
public DeflaterOutputStream(OutputStream out, boolean syncFlush) {
162-
this(out, new Deflater(), 512, syncFlush);
182+
this(out, new Deflater(), DEFAULT_BUF_SIZE, syncFlush);
163183
usesDefaultDeflater = true;
164184
}
165185

@@ -182,6 +202,7 @@ public DeflaterOutputStream(OutputStream out) {
182202
* @param b the byte to be written
183203
* @exception IOException if an I/O error has occurred
184204
*/
205+
@Override
185206
public void write(int b) throws IOException {
186207
byte[] buf = new byte[1];
187208
buf[0] = (byte)(b & 0xff);
@@ -196,6 +217,7 @@ public void write(int b) throws IOException {
196217
* @param len the length of the data
197218
* @exception IOException if an I/O error has occurred
198219
*/
220+
@Override
199221
public void write(byte[] b, int off, int len) throws IOException {
200222
if (def.finished()) {
201223
throw new IOException("write beyond end of stream");
@@ -239,6 +261,7 @@ public void finish() throws IOException {
239261
* underlying stream.
240262
* @exception IOException if an I/O error has occurred
241263
*/
264+
@Override
242265
public void close() throws IOException {
243266
if (!closed) {
244267
try {
@@ -278,13 +301,20 @@ protected void deflate() throws IOException {
278301
*
279302
* @since 1.7
280303
*/
304+
@Override
281305
public void flush() throws IOException {
282306
if (syncFlush && !def.finished()) {
283307
int len = 0;
284-
while ((len = def.deflate(buf, 0, buf.length, Deflater.SYNC_FLUSH)) > 0)
285-
{
286-
out.write(buf, 0, len);
287-
if (len < buf.length)
308+
// For SYNC_FLUSH, the Deflater.deflate() expects the callers
309+
// to use a buffer whose length is greater than 6 to avoid
310+
// flush marker (5 bytes) being repeatedly output to the output buffer
311+
// every time it is invoked.
312+
final byte[] flushBuf = buf.length < SYNC_FLUSH_MIN_BUF_SIZE
313+
? new byte[DEFAULT_BUF_SIZE]
314+
: buf;
315+
while ((len = def.deflate(flushBuf, 0, flushBuf.length, Deflater.SYNC_FLUSH)) > 0) {
316+
out.write(flushBuf, 0, len);
317+
if (len < flushBuf.length)
288318
break;
289319
}
290320
}

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

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

113113
/**
@@ -129,7 +129,7 @@ public GZIPOutputStream(OutputStream out) throws IOException {
129129
public GZIPOutputStream(OutputStream out, boolean syncFlush)
130130
throws IOException
131131
{
132-
this(out, 512, syncFlush);
132+
this(out, DeflaterOutputStream.DEFAULT_BUF_SIZE, syncFlush);
133133
}
134134

135135
/**

0 commit comments

Comments
 (0)