< prev index next >

test/jdk/java/util/zip/ZipFile/TestCleaner.java

Print this page




  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /* @test
  25  * @bug 8185582 8197989
  26  * @modules java.base/java.util.zip:open java.base/jdk.internal.vm.annotation
  27  * @summary Check the resources of Inflater, Deflater and ZipFile are always
  28  *          cleaned/released when the instance is not unreachable
  29  */
  30 
  31 import java.io.*;
  32 import java.lang.reflect.*;
  33 import java.util.*;
  34 import java.util.concurrent.CountDownLatch;
  35 import java.util.concurrent.TimeUnit;
  36 import java.util.zip.*;
  37 import jdk.internal.vm.annotation.DontInline;
  38 import static java.nio.charset.StandardCharsets.US_ASCII;
  39 
  40 public class TestCleaner {
  41 
  42     public static void main(String[] args) throws Throwable {
  43         testDeInflater();
  44         testZipFile();
  45     }
  46 
  47     private static long addrOf(Object obj) {
  48         try {
  49             Field addr = obj.getClass().getDeclaredField("address");
  50             if (!addr.trySetAccessible()) {
  51                 return -1;
  52             }
  53             return addr.getLong(obj);
  54         } catch (Exception x) {
  55             return -1;
  56         }
  57     }
  58 
  59     private static class SubclassedInflater extends Inflater {
  60         CountDownLatch endCountDown;
  61 
  62         SubclassedInflater(CountDownLatch endCountDown) {
  63             this.endCountDown = endCountDown;
  64         }
  65 
  66         @Override
  67         public void end() {
  68             super.end();
  69             endCountDown.countDown();
  70         }
  71     }
  72 
  73     private static class SubclassedDeflater extends Deflater {
  74         CountDownLatch endCountDown;
  75 
  76         SubclassedDeflater(CountDownLatch endCountDown) {
  77             this.endCountDown = endCountDown;
  78         }
  79 
  80         @Override
  81         public void end() {
  82             super.end();
  83             endCountDown.countDown();
  84         }
  85     }
  86 
  87     // verify the "native resource" of In/Deflater has been cleaned
  88     private static void testDeInflater() throws Throwable {
  89         Field zsRefDef = Deflater.class.getDeclaredField("zsRef");
  90         Field zsRefInf = Inflater.class.getDeclaredField("zsRef");
  91         if (!zsRefDef.trySetAccessible() || !zsRefInf.trySetAccessible()) {
  92             throw new RuntimeException("'zsRef' is not accesible");
  93         }
  94         if (addrOf(zsRefDef.get(new Deflater())) == -1 ||
  95             addrOf(zsRefInf.get(new Inflater())) == -1) {
  96             throw new RuntimeException("'addr' is not accesible");
  97         }
  98         List<Object> list = new ArrayList<>();
  99         byte[] buf1 = new byte[1024];
 100         byte[] buf2 = new byte[1024];
 101         for (int i = 0; i < 10; i++) {
 102             var def = new Deflater();
 103             list.add(zsRefDef.get(def));
 104             def.setInput("hello".getBytes());
 105             def.finish();
 106             int n = def.deflate(buf1);
 107 
 108             var inf = new Inflater();
 109             list.add(zsRefInf.get(inf));
 110             inf.setInput(buf1, 0, n);
 111             n = inf.inflate(buf2);
 112             if (!"hello".equals(new String(buf2, 0, n))) {
 113                 throw new RuntimeException("compression/decompression failed");
 114             }
 115         }
 116 
 117         int n = 10;
 118         long cnt = list.size();
 119         while (n-- > 0 && cnt != 0) {
 120             Thread.sleep(100);
 121             System.gc();
 122             cnt = list.stream().filter(o -> addrOf(o) != 0).count();
 123         }
 124         if (cnt != 0)
 125             throw new RuntimeException("cleaner failed to clean : " + cnt);
 126 
 127         // test subclassed Deflater/Inflater, for behavioral compatibility.
 128         // should be removed if the finalize() method is finally removed.
 129         var endCountDown = new CountDownLatch(20);
 130         for (int i = 0; i < 10; i++) {
 131             var def = new SubclassedDeflater(endCountDown);
 132             def.setInput("hello".getBytes());
 133             def.finish();
 134             n = def.deflate(buf1);
 135 
 136             var inf = new SubclassedInflater(endCountDown);
 137             inf.setInput(buf1, 0, n);
 138             n = inf.inflate(buf2);
 139             if (!"hello".equals(new String(buf2, 0, n))) {
 140                 throw new RuntimeException("compression/decompression failed");
 141             }
 142         }
 143         while (!endCountDown.await(10, TimeUnit.MILLISECONDS)) {
 144             System.gc();
 145         }
 146         if (endCountDown.getCount() != 0)
 147             throw new RuntimeException("finalizer failed to clean : " +
 148                 endCountDown.getCount());
 149     }
 150 
 151     private static class SubclassedZipFile extends ZipFile {
 152         CountDownLatch closeCountDown;
 153 
 154         SubclassedZipFile(File f, CountDownLatch closeCountDown)
 155             throws IOException {
 156             super(f);
 157             this.closeCountDown = closeCountDown;
 158         }
 159 
 160         @Override
 161         public void close() throws IOException {
 162             closeCountDown.countDown();
 163             super.close();
 164         }
 165     }
 166 
 167     @DontInline
 168     private static Object openAndCloseZipFile(File zip) throws Throwable {
 169         try {
 170             try (var fos = new FileOutputStream(zip);
 171                  var zos = new ZipOutputStream(fos)) {
 172                 zos.putNextEntry(new ZipEntry("hello"));
 173                 zos.write("hello".getBytes(US_ASCII));
 174                 zos.closeEntry();
 175             }
 176 
 177             var zf = new ZipFile(zip);
 178             var es = zf.entries();
 179             while (es.hasMoreElements()) {
 180                 zf.getInputStream(es.nextElement()).read();
 181             }
 182 
 183             Field fieldRes = ZipFile.class.getDeclaredField("res");
 184             if (!fieldRes.trySetAccessible()) {
 185                 throw new RuntimeException("'ZipFile.res' is not accesible");
 186             }
 187             Object zfRes = fieldRes.get(zf);
 188             if (zfRes == null) {
 189                 throw new RuntimeException("'ZipFile.res' is null");
 190             }
 191             Field fieldZsrc = zfRes.getClass().getDeclaredField("zsrc");
 192             if (!fieldZsrc.trySetAccessible()) {
 193                 throw new RuntimeException("'ZipFile.zsrc' is not accesible");
 194             }
 195             return fieldZsrc.get(zfRes);
 196         } finally {
 197             zip.delete();
 198         }
 199     }
 200 
 201     @DontInline
 202     private static void openAndCloseSubZipFile(File zip, CountDownLatch closeCountDown)
 203         throws Throwable {
 204         try {
 205             try (var fos = new FileOutputStream(zip);
 206                  var zos = new ZipOutputStream(fos)) {
 207                 zos.putNextEntry(new ZipEntry("hello"));
 208                 zos.write("hello".getBytes(US_ASCII));
 209                 zos.closeEntry();
 210             }
 211             var zf = new SubclassedZipFile(zip, closeCountDown);
 212             var es = zf.entries();
 213             while (es.hasMoreElements()) {
 214                 zf.getInputStream(es.nextElement()).read();
 215             }
 216             es = null;
 217             zf = null;
 218         } finally {
 219             zip.delete();
 220         }
 221     }
 222 
 223     private static void testZipFile() throws Throwable {
 224         File dir = new File(System.getProperty("test.dir", "."));
 225         File zip = File.createTempFile("testzf", "zip", dir);
 226 
 227         Object zsrc = openAndCloseZipFile(zip);
 228         if (zsrc != null) {
 229             Field zfileField = zsrc.getClass().getDeclaredField("zfile");
 230             if (!zfileField.trySetAccessible()) {
 231                 throw new RuntimeException("'ZipFile.Source.zfile' is not accesible");
 232             }
 233             //System.out.println("zffile: " +  zfileField.get(zsrc));
 234             int n = 10;
 235             while (n-- > 0 && zfileField.get(zsrc) != null) {
 236                 System.out.println("waiting gc ... " + n);
 237                 System.gc();
 238                 Thread.sleep(100);
 239             }
 240             if (zfileField.get(zsrc) != null) {
 241                 throw new RuntimeException("cleaner failed to clean zipfile.");
 242             }
 243         }
 244 
 245         // test subclassed ZipFile, for behavioral compatibility.
 246         // should be removed if the finalize() method is finally removed.
 247         var closeCountDown = new CountDownLatch(1);
 248         openAndCloseSubZipFile(zip, closeCountDown);
 249         while (!closeCountDown.await(10, TimeUnit.MILLISECONDS)) {
 250             System.gc();
 251         }
 252         if (closeCountDown.getCount() != 0)
 253             throw new RuntimeException("finalizer failed to clean : " +
 254                 closeCountDown.getCount());
 255     }
 256 }


  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /* @test
  25  * @bug 8185582 8197989
  26  * @modules java.base/java.util.zip:open java.base/jdk.internal.vm.annotation
  27  * @summary Check the resources of Inflater, Deflater and ZipFile are always
  28  *          cleaned/released when the instance is not unreachable
  29  */
  30 
  31 import java.io.*;
  32 import java.lang.reflect.*;
  33 import java.util.*;


  34 import java.util.zip.*;
  35 import jdk.internal.vm.annotation.DontInline;
  36 import static java.nio.charset.StandardCharsets.US_ASCII;
  37 
  38 public class TestCleaner {
  39 
  40     public static void main(String[] args) throws Throwable {
  41         testDeInflater();
  42         testZipFile();
  43     }
  44 
  45     private static long addrOf(Object obj) {
  46         try {
  47             Field addr = obj.getClass().getDeclaredField("address");
  48             if (!addr.trySetAccessible()) {
  49                 return -1;
  50             }
  51             return addr.getLong(obj);
  52         } catch (Exception x) {
  53             return -1;
  54         }
  55     }
  56 




























  57     // verify the "native resource" of In/Deflater has been cleaned
  58     private static void testDeInflater() throws Throwable {
  59         Field zsRefDef = Deflater.class.getDeclaredField("zsRef");
  60         Field zsRefInf = Inflater.class.getDeclaredField("zsRef");
  61         if (!zsRefDef.trySetAccessible() || !zsRefInf.trySetAccessible()) {
  62             throw new RuntimeException("'zsRef' is not accesible");
  63         }
  64         if (addrOf(zsRefDef.get(new Deflater())) == -1 ||
  65             addrOf(zsRefInf.get(new Inflater())) == -1) {
  66             throw new RuntimeException("'addr' is not accesible");
  67         }
  68         List<Object> list = new ArrayList<>();
  69         byte[] buf1 = new byte[1024];
  70         byte[] buf2 = new byte[1024];
  71         for (int i = 0; i < 10; i++) {
  72             var def = new Deflater();
  73             list.add(zsRefDef.get(def));
  74             def.setInput("hello".getBytes());
  75             def.finish();
  76             int n = def.deflate(buf1);
  77 
  78             var inf = new Inflater();
  79             list.add(zsRefInf.get(inf));
  80             inf.setInput(buf1, 0, n);
  81             n = inf.inflate(buf2);
  82             if (!"hello".equals(new String(buf2, 0, n))) {
  83                 throw new RuntimeException("compression/decompression failed");
  84             }
  85         }
  86 
  87         int n = 10;
  88         long cnt = list.size();
  89         while (n-- > 0 && cnt != 0) {
  90             Thread.sleep(100);
  91             System.gc();
  92             cnt = list.stream().filter(o -> addrOf(o) != 0).count();
  93         }
  94         if (cnt != 0)
  95             throw new RuntimeException("cleaner failed to clean : " + cnt);
  96 






































  97     }
  98 
  99     @DontInline
 100     private static Object openAndCloseZipFile(File zip) throws Throwable {
 101         try {
 102             try (var fos = new FileOutputStream(zip);
 103                  var zos = new ZipOutputStream(fos)) {
 104                 zos.putNextEntry(new ZipEntry("hello"));
 105                 zos.write("hello".getBytes(US_ASCII));
 106                 zos.closeEntry();
 107             }
 108 
 109             var zf = new ZipFile(zip);
 110             var es = zf.entries();
 111             while (es.hasMoreElements()) {
 112                 zf.getInputStream(es.nextElement()).read();
 113             }
 114 
 115             Field fieldRes = ZipFile.class.getDeclaredField("res");
 116             if (!fieldRes.trySetAccessible()) {
 117                 throw new RuntimeException("'ZipFile.res' is not accesible");
 118             }
 119             Object zfRes = fieldRes.get(zf);
 120             if (zfRes == null) {
 121                 throw new RuntimeException("'ZipFile.res' is null");
 122             }
 123             Field fieldZsrc = zfRes.getClass().getDeclaredField("zsrc");
 124             if (!fieldZsrc.trySetAccessible()) {
 125                 throw new RuntimeException("'ZipFile.zsrc' is not accesible");
 126             }
 127             return fieldZsrc.get(zfRes);
 128         } finally {
 129             zip.delete();
 130         }
 131     }
 132 





















 133 
 134     private static void testZipFile() throws Throwable {
 135         File dir = new File(System.getProperty("test.dir", "."));
 136         File zip = File.createTempFile("testzf", "zip", dir);
 137 
 138         Object zsrc = openAndCloseZipFile(zip);
 139         if (zsrc != null) {
 140             Field zfileField = zsrc.getClass().getDeclaredField("zfile");
 141             if (!zfileField.trySetAccessible()) {
 142                 throw new RuntimeException("'ZipFile.Source.zfile' is not accesible");
 143             }
 144             //System.out.println("zffile: " +  zfileField.get(zsrc));
 145             int n = 10;
 146             while (n-- > 0 && zfileField.get(zsrc) != null) {
 147                 System.out.println("waiting gc ... " + n);
 148                 System.gc();
 149                 Thread.sleep(100);
 150             }
 151             if (zfileField.get(zsrc) != null) {
 152                 throw new RuntimeException("cleaner failed to clean zipfile.");
 153             }
 154         }











 155     }
 156 }
< prev index next >