--- /dev/null 2017-10-31 17:22:21.921871366 +0100 +++ new/test/jdk/java/util/zip/ZipFile/TestCleaner.java 2017-10-31 23:27:37.062557327 +0100 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2017, 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 8185582 + * @modules java.base/java.util.zip:open + * @summary Check the resources of Inflater, Deflater and ZipFile are always + * cleaned/released when the instane is not unreachable + */ + +import java.io.*; +import java.lang.ref.Cleaner; +import java.lang.reflect.*; +import java.util.*; +import java.util.zip.*; + +import static java.nio.charset.StandardCharsets.US_ASCII; + + +public class TestCleaner { + + public static void main(String[] args) throws Throwable { + testDeInflater(); + testZipFile(); + } + + private static long addrOf(Object obj) { + try { + return ((Cleaner.LongCleanableResource) obj).value(); + } catch (IllegalStateException x) { // already cleaned + return 0; + } + } + + // verify the "native resource" of In/Deflater has been cleaned + private static void testDeInflater() throws Throwable { + Field zsRefDef = Deflater.class.getDeclaredField("zsRef"); + Field zsRefInf = Inflater.class.getDeclaredField("zsRef"); + if (!zsRefDef.trySetAccessible() || !zsRefInf.trySetAccessible()) { + throw new RuntimeException("'zsRef' is not accesible"); + } + List list = new ArrayList<>(); + byte[] buf1 = new byte[1024]; + byte[] buf2 = new byte[1024]; + for (int i = 0; i < 10; i++) { + Deflater def = new Deflater(); + list.add(zsRefDef.get(def)); + def.setInput("hello".getBytes()); + def.finish(); + int n = def.deflate(buf1); + + Inflater inf = new Inflater(); + list.add(zsRefInf.get(inf)); + inf.setInput(buf1, 0, n); + n = inf.inflate(buf2); + if (!"hello".equals(new String(buf2, 0, n))) { + throw new RuntimeException("compression/decompression failed"); + } + } + + int n = 10; + long cnt = list.size(); + while (n-- > 0 && cnt != 0) { + Thread.sleep(100); + System.gc(); + cnt = list.stream().filter(o -> addrOf(o) != 0).count(); + } + if (cnt != 0) + throw new RuntimeException("cleaner failed to clean : " + cnt); + } + + private static void testZipFile() throws Throwable { + File dir = new File(System.getProperty("test.dir", ".")); + File zip = File.createTempFile("testzf", "zip", dir); + Object zsrc = null; + try { + try (FileOutputStream fos = new FileOutputStream(zip); + ZipOutputStream zos = new ZipOutputStream(fos)) { + zos.putNextEntry(new ZipEntry("hello")); + zos.write("hello".getBytes(US_ASCII)); + zos.closeEntry(); + } + + ZipFile zf = new ZipFile(zip); + Enumeration es = zf.entries(); + while (es.hasMoreElements()) { + zf.getInputStream(es.nextElement()).read(); + } + + Field fieldZsrc = ZipFile.class.getDeclaredField("zsrc"); + if (!fieldZsrc.trySetAccessible()) { + throw new RuntimeException("'ZipFile.zsrc' is not accesible"); + } + zsrc = fieldZsrc.get(zf); + + } finally { + zip.delete(); + } + + if (zsrc != null) { + Field zfileField = zsrc.getClass().getDeclaredField("zfile"); + if (!zfileField.trySetAccessible()) { + throw new RuntimeException("'ZipFile.Source.zfile' is not accesible"); + } + //System.out.println("zffile: " + zfileField.get(zsrc)); + int n = 10; + while (n-- > 0 && zfileField.get(zsrc) != null) { + System.out.println("waiting gc ... " + n); + System.gc(); + Thread.sleep(100); + } + if (zfileField.get(zsrc) != null) { + throw new RuntimeException("cleaner failed to clean zipfile."); + } + } + } + +}