OpenJDK / jdk-updates / jdk12u
changeset 7550:700dd1df3aa8
7003462: cannot read InputStream returned by java.util.ZipFile.getInputStream(ZipEntry)
Summary: The returned InflatedInputStream object should be kept in map streams
Reviewed-by: alanb
author | sherman |
---|---|
date | Mon, 13 Dec 2010 14:12:56 -0800 |
parents | dc320f7ef48f |
children | dc77388d186a |
files | jdk/src/share/classes/java/util/zip/ZipFile.java jdk/test/java/util/zip/ZipFile/FinalizeInflater.java |
diffstat | 2 files changed, 126 insertions(+), 49 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/src/share/classes/java/util/zip/ZipFile.java Mon Dec 13 15:07:20 2010 +0000 +++ b/jdk/src/share/classes/java/util/zip/ZipFile.java Mon Dec 13 14:12:56 2010 -0800 @@ -315,7 +315,7 @@ private static native void freeEntry(long jzfile, long jzentry); // the outstanding inputstreams that need to be closed. - private Set<ZipFileInputStream> streams = new HashSet<ZipFileInputStream>(); + private Set<InputStream> streams = new HashSet<>(); /** * Returns an input stream for reading the contents of the specified @@ -348,55 +348,58 @@ return null; } in = new ZipFileInputStream(jzentry); - streams.add(in); - } - final ZipFileInputStream zfin = in; - switch (getEntryMethod(jzentry)) { - case STORED: - return zfin; - case DEFLATED: - // MORE: Compute good size for inflater stream: - long size = getEntrySize(jzentry) + 2; // Inflater likes a bit of slack - if (size > 65536) size = 8192; - if (size <= 0) size = 4096; - return new InflaterInputStream(zfin, getInflater(), (int)size) { - private boolean isClosed = false; - public void close() throws IOException { - if (!isClosed) { - releaseInflater(inf); - this.in.close(); - isClosed = true; + switch (getEntryMethod(jzentry)) { + case STORED: + streams.add(in); + return in; + case DEFLATED: + final ZipFileInputStream zfin = in; + // MORE: Compute good size for inflater stream: + long size = getEntrySize(jzentry) + 2; // Inflater likes a bit of slack + if (size > 65536) size = 8192; + if (size <= 0) size = 4096; + InputStream is = new InflaterInputStream(zfin, getInflater(), (int)size) { + private boolean isClosed = false; + + public void close() throws IOException { + if (!isClosed) { + super.close(); + releaseInflater(inf); + isClosed = true; + } } - } - // Override fill() method to provide an extra "dummy" byte - // at the end of the input stream. This is required when - // using the "nowrap" Inflater option. - protected void fill() throws IOException { - if (eof) { - throw new EOFException( - "Unexpected end of ZLIB input stream"); + // Override fill() method to provide an extra "dummy" byte + // at the end of the input stream. This is required when + // using the "nowrap" Inflater option. + protected void fill() throws IOException { + if (eof) { + throw new EOFException( + "Unexpected end of ZLIB input stream"); + } + len = this.in.read(buf, 0, buf.length); + if (len == -1) { + buf[0] = 0; + len = 1; + eof = true; + } + inf.setInput(buf, 0, len); } - len = this.in.read(buf, 0, buf.length); - if (len == -1) { - buf[0] = 0; - len = 1; - eof = true; + private boolean eof; + + public int available() throws IOException { + if (isClosed) + return 0; + long avail = zfin.size() - inf.getBytesWritten(); + return avail > (long) Integer.MAX_VALUE ? + Integer.MAX_VALUE : (int) avail; } - inf.setInput(buf, 0, len); - } - private boolean eof; - - public int available() throws IOException { - if (isClosed) - return 0; - long avail = zfin.size() - inf.getBytesWritten(); - return avail > (long) Integer.MAX_VALUE ? - Integer.MAX_VALUE : (int) avail; - } - }; - default: - throw new ZipException("invalid compression method"); + }; + streams.add(is); + return is; + default: + throw new ZipException("invalid compression method"); + } } } @@ -539,9 +542,9 @@ closeRequested = true; if (streams.size() !=0) { - Set<ZipFileInputStream> copy = streams; - streams = new HashSet<ZipFileInputStream>(); - for (ZipFileInputStream is: copy) + Set<InputStream> copy = streams; + streams = new HashSet<InputStream>(); + for (InputStream is: copy) is.close(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/zip/ZipFile/FinalizeInflater.java Mon Dec 13 14:12:56 2010 -0800 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2010, 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 + @bug 7003462 + @summary Make sure cached Inflater does not get finalized. + */ + +import java.io.File; +import java.io.InputStream; +import java.io.IOException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +public class FinalizeInflater { + + public static void main(String[] args) throws Throwable { + try (ZipFile zf = new ZipFile(new File(System.getProperty("test.src", "."), "input.zip"))) + { + ZipEntry ze = zf.getEntry("ReadZip.java"); + read(zf.getInputStream(ze)); + System.gc(); + System.runFinalization(); + System.gc(); + // read again + read(zf.getInputStream(ze)); + } + } + + private static void read(InputStream is) + throws IOException + { + Wrapper wrapper = new Wrapper(is); + byte[] buffer = new byte[32]; + try { + while(is.read(buffer)>0){} + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + + static class Wrapper{ + InputStream is; + public Wrapper(InputStream is) { + this.is = is; + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + is.close(); + } + } +}