代码拉取完成,页面将自动刷新
---
jdk/make/mapfiles/libzip/mapfile-vers | 5 +-
.../share/classes/java/util/zip/Deflater.java | 36 +++++--
.../java/util/zip/GZIPInputStream.java | 73 +++++++++++---
.../java/util/zip/GZIPOutputStream.java | 44 +++++----
.../share/classes/java/util/zip/Inflater.java | 37 +++++---
.../java/util/zip/InflaterInputStream.java | 25 +++++
jdk/src/share/lib/security/java.policy | 2 +
jdk/src/share/native/java/util/zip/Deflater.c | 9 +-
jdk/src/share/native/java/util/zip/Inflater.c | 73 +-------------
.../java/util/zip/GZIP/TestAvailable.java | 94 +++++++++++++++++++
10 files changed, 272 insertions(+), 126 deletions(-)
create mode 100644 jdk/test/java/util/zip/GZIP/TestAvailable.java
diff --git a/jdk/make/mapfiles/libzip/mapfile-vers b/jdk/make/mapfiles/libzip/mapfile-vers
index 5c6d27d0d..79ef59e5f 100644
--- a/jdk/make/mapfiles/libzip/mapfile-vers
+++ b/jdk/make/mapfiles/libzip/mapfile-vers
@@ -38,16 +38,15 @@ SUNWprivate_1.1 {
Java_java_util_zip_Deflater_end;
Java_java_util_zip_Deflater_getAdler;
Java_java_util_zip_Deflater_init;
- Java_java_util_zip_Deflater_initKae;
+ Java_java_util_zip_Deflater_initKAE;
Java_java_util_zip_Deflater_initIDs;
Java_java_util_zip_Deflater_reset;
Java_java_util_zip_Deflater_setDictionary;
Java_java_util_zip_Inflater_end;
Java_java_util_zip_Inflater_getAdler;
Java_java_util_zip_Inflater_inflateBytes;
- Java_java_util_zip_Inflater_inflateBytesKAE;
Java_java_util_zip_Inflater_init;
- Java_java_util_zip_Inflater_initKae;
+ Java_java_util_zip_Inflater_initKAE;
Java_java_util_zip_Inflater_initIDs;
Java_java_util_zip_Inflater_reset;
Java_java_util_zip_Inflater_setDictionary;
diff --git a/jdk/src/share/classes/java/util/zip/Deflater.java b/jdk/src/share/classes/java/util/zip/Deflater.java
index a4ea40cf8..509808349 100644
--- a/jdk/src/share/classes/java/util/zip/Deflater.java
+++ b/jdk/src/share/classes/java/util/zip/Deflater.java
@@ -81,7 +81,6 @@ class Deflater {
private boolean finish, finished;
private long bytesRead;
private long bytesWritten;
- private boolean defalterUseKae;
/**
* Compression method for the deflate algorithm (the only one currently
@@ -169,13 +168,20 @@ class Deflater {
public Deflater(int level, boolean nowrap) {
this.level = level;
this.strategy = DEFAULT_STRATEGY;
- if (("true".equals(System.getProperty("GZIP_USE_KAE", "false"))) &&
- ("aarch64".equals(System.getProperty("os.arch")))) {
- this.defalterUseKae = true;
- }
- this.zsRef = defalterUseKae ?
- new ZStreamRef(initKae(level, DEFAULT_STRATEGY)) :
- new ZStreamRef(init(level, DEFAULT_STRATEGY, nowrap));
+ this.zsRef = new ZStreamRef(init(level, DEFAULT_STRATEGY, nowrap));
+ }
+
+ /**
+ * Creates a new compressor using the specified compression level
+ * and windowBits.
+ * This method is mainly used to support the KAE-zip feature.
+ * @param level the compression level (0-9)
+ * @param windowBits compression format (-15~31)
+ */
+ public Deflater(int level, int windowBits) {
+ this.level = level;
+ this.strategy = DEFAULT_STRATEGY;
+ this.zsRef = new ZStreamRef(initKAE(level, DEFAULT_STRATEGY, windowBits));
}
/**
@@ -535,6 +541,18 @@ class Deflater {
}
}
+ /**
+ * Resets deflater so that a new set of input data can be processed.
+ * Java fields are not initialized.
+ * This method is mainly used to support the KAE-zip feature.
+ */
+ public void resetKAE() {
+ synchronized (zsRef) {
+ ensureOpen();
+ reset(zsRef.address());
+ }
+ }
+
/**
* Closes the compressor and discards any unprocessed input.
* This method should be called when the compressor is no longer
@@ -578,7 +596,7 @@ class Deflater {
private static native void initIDs();
private native static long init(int level, int strategy, boolean nowrap);
- private native static long initKae(int level, int strategy);
+ private native static long initKAE(int level, int strategy, int windowBits);
private native static void setDictionary(long addr, byte[] b, int off, int len);
private native int deflateBytes(long addr, byte[] b, int off, int len,
int flush);
diff --git a/jdk/src/share/classes/java/util/zip/GZIPInputStream.java b/jdk/src/share/classes/java/util/zip/GZIPInputStream.java
index 7fb753729..10d044caf 100644
--- a/jdk/src/share/classes/java/util/zip/GZIPInputStream.java
+++ b/jdk/src/share/classes/java/util/zip/GZIPInputStream.java
@@ -54,10 +54,22 @@ class GZIPInputStream extends InflaterInputStream {
private boolean closed = false;
- /*
- * GZIP use KAE.
+ /**
+ * The field is mainly used to support the KAE-zip feature.
*/
- private boolean gzipUseKae = false;
+ private static boolean GZIP_USE_KAE = false;
+
+ private static int WINDOWBITS = 31;
+
+ private static int FLUSHKAE = 2;
+
+ static {
+ if ("aarch64".equals(System.getProperty("os.arch"))) {
+ GZIP_USE_KAE = Boolean.parseBoolean(System.getProperty("GZIP_USE_KAE", "false"));
+ WINDOWBITS = Integer.parseInt(System.getProperty("WINDOWBITS", "31"));
+ FLUSHKAE = Integer.parseInt(System.getProperty("FLUSHKAE", "2"));
+ }
+ }
/**
* Check to make sure that this stream has not been closed
@@ -79,14 +91,13 @@ class GZIPInputStream extends InflaterInputStream {
* @exception IllegalArgumentException if {@code size <= 0}
*/
public GZIPInputStream(InputStream in, int size) throws IOException {
- super(in, new Inflater(true), size);
+ super(in, GZIP_USE_KAE ? new Inflater(WINDOWBITS, FLUSHKAE) : new Inflater(true), size);
usesDefaultInflater = true;
- if (("true".equals(System.getProperty("GZIP_USE_KAE", "false"))) &&
- ("aarch64".equals(System.getProperty("os.arch")))) {
- gzipUseKae = true;
- }
- // file header will be readed by kae zlib when use kae
- if (gzipUseKae) return;
+
+ // When GZIP_USE_KAE is true, the header of the file is readed
+ // through the native zlib library, not in java code.
+ if (GZIP_USE_KAE) return;
+
readHeader(in);
}
@@ -127,13 +138,16 @@ class GZIPInputStream extends InflaterInputStream {
}
int n = super.read(buf, off, len);
if (n == -1) {
- if (readTrailer())
+ if (GZIP_USE_KAE ? readTrailerKAE() : readTrailer())
eos = true;
else
return this.read(buf, off, len);
} else {
crc.update(buf, off, n);
}
+ if (GZIP_USE_KAE && inf.finished()) {
+ if (readTrailerKAE()) eos = true;
+ }
return n;
}
@@ -220,9 +234,7 @@ class GZIPInputStream extends InflaterInputStream {
* data set)
*/
private boolean readTrailer() throws IOException {
- // file trailer will be readed by kae zlib when use kae
- if (gzipUseKae) return true;
-
+ if (GZIP_USE_KAE) return true;
InputStream in = this.in;
int n = inf.getRemaining();
if (n > 0) {
@@ -251,6 +263,39 @@ class GZIPInputStream extends InflaterInputStream {
return false;
}
+ /*
+ * Reads GZIP member trailer and returns true if the eos
+ * reached, false if there are more (concatenated gzip
+ * data set)
+ *
+ * This method is mainly used to support the KAE-zip feature.
+ */
+ private boolean readTrailerKAE() throws IOException {
+ InputStream in = this.in;
+ int n = inf.getRemaining();
+ if (n > 0) {
+ in = new SequenceInputStream(
+ new ByteArrayInputStream(buf, len - n, n),
+ new FilterInputStream(in) {
+ public void close() throws IOException {}
+ });
+ }
+ // If there are more bytes available in "in" or the leftover in the "inf" is > 18 bytes:
+ // next.header.min(10) + next.trailer(8), try concatenated case
+
+ if (n > 18) {
+ inf.reset();
+ inf.setInput(buf, len - n, n);
+ } else {
+ try {
+ fillKAE(n);
+ } catch (IOException e) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/*
* Reads unsigned integer in Intel byte order.
*/
diff --git a/jdk/src/share/classes/java/util/zip/GZIPOutputStream.java b/jdk/src/share/classes/java/util/zip/GZIPOutputStream.java
index 0f0be98bb..8eae40739 100644
--- a/jdk/src/share/classes/java/util/zip/GZIPOutputStream.java
+++ b/jdk/src/share/classes/java/util/zip/GZIPOutputStream.java
@@ -52,10 +52,19 @@ class GZIPOutputStream extends DeflaterOutputStream {
*/
private final static int TRAILER_SIZE = 8;
- /*
- * GZIP use KAE.
+ /**
+ * The field is mainly used to support the KAE-zip feature.
*/
- private boolean gzipUseKae = false;
+ private static boolean GZIP_USE_KAE = false;
+
+ private static int WINDOWBITS = 31;
+
+ static {
+ if ("aarch64".equals(System.getProperty("os.arch"))) {
+ GZIP_USE_KAE = Boolean.parseBoolean(System.getProperty("GZIP_USE_KAE", "false"));
+ WINDOWBITS = Integer.parseInt(System.getProperty("WINDOWBITS", "31"));
+ }
+ }
/**
* Creates a new output stream with the specified buffer size.
@@ -92,16 +101,15 @@ class GZIPOutputStream extends DeflaterOutputStream {
public GZIPOutputStream(OutputStream out, int size, boolean syncFlush)
throws IOException
{
- super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true),
+ super(out, GZIP_USE_KAE ? new Deflater(Deflater.DEFAULT_COMPRESSION, WINDOWBITS) :
+ new Deflater(Deflater.DEFAULT_COMPRESSION, true),
size,
syncFlush);
usesDefaultDeflater = true;
- if (("true".equals(System.getProperty("GZIP_USE_KAE", "false"))) &&
- ("aarch64".equals(System.getProperty("os.arch")))) {
- gzipUseKae = true;
- }
- // file header will be writed by kae zlib when use kae
- if (gzipUseKae) return;
+
+ // When GZIP_USE_KAE is true, the header of the file is written
+ // through the native zlib library, not in java code.
+ if (GZIP_USE_KAE) return;
writeHeader();
crc.reset();
}
@@ -171,9 +179,11 @@ class GZIPOutputStream extends DeflaterOutputStream {
int len = def.deflate(buf, 0, buf.length);
if (def.finished() && len <= buf.length - TRAILER_SIZE) {
// last deflater buffer. Fit trailer at the end
- // file trailer will be writed by kae zlib when use kae
- if (gzipUseKae) {
+ // When GZIP_USE_KAE is true, the trailer of the file is written
+ // through the native zlib library, not in java code.
+ if (GZIP_USE_KAE) {
out.write(buf, 0, len);
+ def.resetKAE();
return;
}
writeTrailer(buf, len);
@@ -184,12 +194,14 @@ class GZIPOutputStream extends DeflaterOutputStream {
if (len > 0)
out.write(buf, 0, len);
}
- // file trailer will be writed by kae zlib when use kae
- if (gzipUseKae) {
- return;
- }
// if we can't fit the trailer at the end of the last
// deflater buffer, we write it separately
+ // When GZIP_USE_KAE is true, the trailer of the file is written
+ // through the native zlib library, not in java code.
+ if (GZIP_USE_KAE) {
+ def.resetKAE();
+ return;
+ }
byte[] trailer = new byte[TRAILER_SIZE];
writeTrailer(trailer, 0);
out.write(trailer);
diff --git a/jdk/src/share/classes/java/util/zip/Inflater.java b/jdk/src/share/classes/java/util/zip/Inflater.java
index 42e90f525..d1074cd8d 100644
--- a/jdk/src/share/classes/java/util/zip/Inflater.java
+++ b/jdk/src/share/classes/java/util/zip/Inflater.java
@@ -80,7 +80,6 @@ class Inflater {
private boolean needDict;
private long bytesRead;
private long bytesWritten;
- private boolean inflaterUseKae;
private static final byte[] defaultBuf = new byte[0];
@@ -101,11 +100,18 @@ class Inflater {
* @param nowrap if true then support GZIP compatible compression
*/
public Inflater(boolean nowrap) {
- if (("true".equals(System.getProperty("GZIP_USE_KAE", "false"))) &&
- ("aarch64".equals(System.getProperty("os.arch")))) {
- inflaterUseKae = true;
- }
- zsRef = inflaterUseKae ? new ZStreamRef(initKae()): new ZStreamRef(init(nowrap));
+ zsRef = new ZStreamRef(init(nowrap));
+ }
+
+ /**
+ * Creates a new decompressor.
+ * This method is mainly used to support the KAE-zip feature.
+ *
+ * @param windowBits compression format (-15~31)
+ * @param flushKAE inflate flush type (0~6)
+ */
+ public Inflater(int windowBits, int flushKAE) {
+ this.zsRef = new ZStreamRef(initKAE(windowBits, flushKAE));
}
/**
@@ -261,9 +267,7 @@ class Inflater {
synchronized (zsRef) {
ensureOpen();
int thisLen = this.len;
- int n = this.inflaterUseKae ?
- inflateBytesKAE(zsRef.address(), b, off, len) :
- inflateBytes(zsRef.address(), b, off, len);
+ int n = inflateBytes(zsRef.address(), b, off, len);
bytesWritten += n;
bytesRead += (thisLen - this.len);
return n;
@@ -365,6 +369,17 @@ class Inflater {
}
}
+ /**
+ * Resets inflater so that a new set of input data can be processed.
+ * This method is mainly used to support the KAE-zip feature.
+ */
+ public void resetKAE() {
+ synchronized (zsRef) {
+ ensureOpen();
+ reset(zsRef.address());
+ }
+ }
+
/**
* Closes the decompressor and discards any unprocessed input.
* This method should be called when the decompressor is no longer
@@ -404,13 +419,11 @@ class Inflater {
private native static void initIDs();
private native static long init(boolean nowrap);
- private native static long initKae();
+ private native static long initKAE(int windowBits, int flushKAE);
private native static void setDictionary(long addr, byte[] b, int off,
int len);
private native int inflateBytes(long addr, byte[] b, int off, int len)
throws DataFormatException;
- private native int inflateBytesKAE(long addr, byte[] b, int off, int len)
- throws DataFormatException;
private native static int getAdler(long addr);
private native static void reset(long addr);
private native static void end(long addr);
diff --git a/jdk/src/share/classes/java/util/zip/InflaterInputStream.java b/jdk/src/share/classes/java/util/zip/InflaterInputStream.java
index 163f619c1..b0ac7dd26 100644
--- a/jdk/src/share/classes/java/util/zip/InflaterInputStream.java
+++ b/jdk/src/share/classes/java/util/zip/InflaterInputStream.java
@@ -179,6 +179,10 @@ class InflaterInputStream extends FilterInputStream {
ensureOpen();
if (reachEOF) {
return 0;
+ } else if (inf.finished()) {
+ // the end of the compressed data stream has been reached
+ reachEOF = true;
+ return 0;
} else {
return 1;
}
@@ -242,6 +246,27 @@ class InflaterInputStream extends FilterInputStream {
inf.setInput(buf, 0, len);
}
+ /**
+ * Fills input buffer with more data to decompress.
+ * This method is mainly used to support the KAE-zip feature.
+ * @param n Maximum Read Bytes
+ * @throws IOException if an I/O error has occurred
+ */
+ protected void fillKAE(int n) throws IOException {
+ ensureOpen();
+ byte[] buftmp = new byte[buf.length];
+ if (n != 0) {
+ System.arraycopy(buf, buf.length - n, buftmp, 0, n);
+ }
+ int kaelen = in.read(buftmp, n, buf.length - n);
+ if (kaelen == -1) {
+ throw new EOFException("Unexpected end of ZLIB input stream");
+ }
+ System.arraycopy(buftmp, 0, buf, buf.length - n - kaelen, n + kaelen);
+ inf.reset();
+ inf.setInput(buf, buf.length - n - kaelen, n + kaelen);
+ }
+
/**
* Tests if this input stream supports the <code>mark</code> and
* <code>reset</code> methods. The <code>markSupported</code>
diff --git a/jdk/src/share/lib/security/java.policy b/jdk/src/share/lib/security/java.policy
index baec2ea15..284e3e334 100644
--- a/jdk/src/share/lib/security/java.policy
+++ b/jdk/src/share/lib/security/java.policy
@@ -50,5 +50,7 @@ grant {
permission java.util.PropertyPermission "sun.security.pkcs11.disableKeyExtraction", "read";
permission java.util.PropertyPermission "GZIP_USE_KAE", "read";
+ permission java.util.PropertyPermission "WINDOWBITS", "read";
+ permission java.util.PropertyPermission "FLUSHKAE", "read";
};
diff --git a/jdk/src/share/native/java/util/zip/Deflater.c b/jdk/src/share/native/java/util/zip/Deflater.c
index 1b048e4f5..b26eb1392 100644
--- a/jdk/src/share/native/java/util/zip/Deflater.c
+++ b/jdk/src/share/native/java/util/zip/Deflater.c
@@ -37,7 +37,6 @@
#include "java_util_zip_Deflater.h"
#define DEF_MEM_LEVEL 8
-#define KAE_DEFLATER_WindowBit 31
static jfieldID levelID;
static jfieldID strategyID;
@@ -106,8 +105,8 @@ Java_java_util_zip_Deflater_init(JNIEnv *env, jclass cls, jint level,
}
JNIEXPORT jlong JNICALL
-Java_java_util_zip_Deflater_initKae(JNIEnv *env, jclass cls, jint level,
- jint strategy)
+Java_java_util_zip_Deflater_initKAE(JNIEnv *env, jclass cls, jint level,
+ jint strategy, jint windowBits)
{
z_stream *strm = calloc(1, sizeof(z_stream));
@@ -116,7 +115,9 @@ Java_java_util_zip_Deflater_initKae(JNIEnv *env, jclass cls, jint level,
return jlong_zero;
} else {
const char *msg;
- int ret = deflateInit2(strm, level, Z_DEFLATED, KAE_DEFLATER_WindowBit, DEF_MEM_LEVEL, strategy);
+ int ret = deflateInit2(strm, level, Z_DEFLATED,
+ windowBits,
+ DEF_MEM_LEVEL, strategy);
switch (ret) {
case Z_OK:
return ptr_to_jlong(strm);
diff --git a/jdk/src/share/native/java/util/zip/Inflater.c b/jdk/src/share/native/java/util/zip/Inflater.c
index fca207215..8317267ff 100644
--- a/jdk/src/share/native/java/util/zip/Inflater.c
+++ b/jdk/src/share/native/java/util/zip/Inflater.c
@@ -41,11 +41,11 @@
#define ThrowDataFormatException(env, msg) \
JNU_ThrowByName(env, "java/util/zip/DataFormatException", msg)
-#define KAE_INFLATER_WindowBit 31
static jfieldID needDictID;
static jfieldID finishedID;
static jfieldID bufID, offID, lenID;
+static jint inflaterFlushType = Z_PARTIAL_FLUSH;
JNIEXPORT void JNICALL
Java_java_util_zip_Inflater_initIDs(JNIEnv *env, jclass cls)
@@ -96,16 +96,17 @@ Java_java_util_zip_Inflater_init(JNIEnv *env, jclass cls, jboolean nowrap)
}
JNIEXPORT jlong JNICALL
-Java_java_util_zip_Inflater_initKae(JNIEnv *env, jclass cls)
+Java_java_util_zip_Inflater_initKAE(JNIEnv *env, jclass cls, jint windowBits, jint flushKAE)
{
z_stream *strm = calloc(1, sizeof(z_stream));
+ inflaterFlushType = flushKAE;
if (strm == NULL) {
JNU_ThrowOutOfMemoryError(env, 0);
return jlong_zero;
} else {
const char *msg;
- int ret = inflateInit2(strm, KAE_INFLATER_WindowBit);
+ int ret = inflateInit2(strm, windowBits);
switch (ret) {
case Z_OK:
return ptr_to_jlong(strm);
@@ -181,71 +182,7 @@ Java_java_util_zip_Inflater_inflateBytes(JNIEnv *env, jobject this, jlong addr,
strm->next_out = (Bytef *) (out_buf + off);
strm->avail_in = this_len;
strm->avail_out = len;
- ret = inflate(strm, Z_PARTIAL_FLUSH);
- (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0);
- (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
-
- switch (ret) {
- case Z_STREAM_END:
- (*env)->SetBooleanField(env, this, finishedID, JNI_TRUE);
- /* fall through */
- case Z_OK:
- this_off += this_len - strm->avail_in;
- (*env)->SetIntField(env, this, offID, this_off);
- (*env)->SetIntField(env, this, lenID, strm->avail_in);
- return (jint) (len - strm->avail_out);
- case Z_NEED_DICT:
- (*env)->SetBooleanField(env, this, needDictID, JNI_TRUE);
- /* Might have consumed some input here! */
- this_off += this_len - strm->avail_in;
- (*env)->SetIntField(env, this, offID, this_off);
- (*env)->SetIntField(env, this, lenID, strm->avail_in);
- return 0;
- case Z_BUF_ERROR:
- return 0;
- case Z_DATA_ERROR:
- ThrowDataFormatException(env, strm->msg);
- return 0;
- case Z_MEM_ERROR:
- JNU_ThrowOutOfMemoryError(env, 0);
- return 0;
- default:
- JNU_ThrowInternalError(env, strm->msg);
- return 0;
- }
-}
-
-JNIEXPORT jint JNICALL
-Java_java_util_zip_Inflater_inflateBytesKAE(JNIEnv *env, jobject this, jlong addr,
- jarray b, jint off, jint len)
-{
- z_stream *strm = jlong_to_ptr(addr);
- jarray this_buf = (jarray)(*env)->GetObjectField(env, this, bufID);
- jint this_off = (*env)->GetIntField(env, this, offID);
- jint this_len = (*env)->GetIntField(env, this, lenID);
-
- jbyte *in_buf;
- jbyte *out_buf;
- int ret;
-
- in_buf = (*env)->GetPrimitiveArrayCritical(env, this_buf, 0);
- if (in_buf == NULL) {
- if (this_len != 0 && (*env)->ExceptionOccurred(env) == NULL)
- JNU_ThrowOutOfMemoryError(env, 0);
- return 0;
- }
- out_buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
- if (out_buf == NULL) {
- (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
- if (len != 0 && (*env)->ExceptionOccurred(env) == NULL)
- JNU_ThrowOutOfMemoryError(env, 0);
- return 0;
- }
- strm->next_in = (Bytef *) (in_buf + this_off);
- strm->next_out = (Bytef *) (out_buf + off);
- strm->avail_in = this_len;
- strm->avail_out = len;
- ret = inflate(strm, Z_SYNC_FLUSH);
+ ret = inflate(strm, inflaterFlushType);
(*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0);
(*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
diff --git a/jdk/test/java/util/zip/GZIP/TestAvailable.java b/jdk/test/java/util/zip/GZIP/TestAvailable.java
new file mode 100644
index 000000000..3dc9b3445
--- /dev/null
+++ b/jdk/test/java/util/zip/GZIP/TestAvailable.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @library /lib/testlibrary/
+ * @build jdk.testlibrary.*
+ * @run main TestAvailable
+ * @bug 7031075
+ * @summary Make sure that available() method behaves as expected.
+ * @key randomness
+ */
+
+import java.io.*;
+import java.util.Random;
+import java.util.zip.*;
+import jdk.testlibrary.RandomFactory;
+
+public class TestAvailable {
+
+ public static void main(String args[]) throws Throwable {
+ Random r = RandomFactory.getRandom();
+ for (int n = 0; n < 10; n++) {
+ byte[] src = new byte[r.nextInt(100)];
+ r.nextBytes(src);
+
+ // test InflaterInputStream
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try (DeflaterOutputStream dos = new DeflaterOutputStream(baos)) {
+ dos.write(src);
+ }
+ try (InflaterInputStream iis = new InflaterInputStream(
+ new ByteArrayInputStream(baos.toByteArray()))) {
+ test(iis, src);
+ }
+
+ // test GZIPInputStream
+ baos = new ByteArrayOutputStream();
+ try (GZIPOutputStream dos = new GZIPOutputStream(baos)) {
+ dos.write(src);
+ }
+ try (GZIPInputStream gis = new GZIPInputStream(
+ new ByteArrayInputStream(baos.toByteArray()))) {
+ test(gis, src);
+ }
+ }
+ }
+
+ private static void test(InputStream is, byte[] expected) throws IOException {
+ int cnt = 0;
+ do {
+ int available = is.available();
+ if (available > 0) {
+ int b = is.read();
+ if (b == -1) {
+ throw new RuntimeException("available() > 0, read() == -1 : failed!");
+ }
+ if (expected[cnt++] != (byte)b) {
+ throw new RuntimeException("read() : failed!");
+ }
+ } else if (available == 0) {
+ if (is.read() != -1) {
+ throw new RuntimeException("available() == 0, read() != -1 : failed!");
+ }
+ break;
+ } else {
+ throw new RuntimeException("available() < 0 : failed!");
+ }
+ } while (true);
+ if (cnt != expected.length) {
+ throw new RuntimeException("read : failed!");
+ }
+ }
+
+}
\ No newline at end of file
--
2.19.1
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。