1 /* 2 * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.util.zip; 27 28 import java.util.function.LongConsumer; 29 import java.util.function.LongSupplier; 30 import java.lang.ref.Cleaner.Cleanable; 31 import jdk.internal.ref.CleanerFactory; 32 33 /** 34 * A reference to the native zlib's z_stream structure. It also 35 * serves as the "cleaner" to clean up the native resource when 36 * the deflater or infalter is ended, closed or cleaned. 37 */ 38 class ZStreamRef implements Runnable { 39 40 private LongConsumer end; 41 private long address; 42 private final Cleanable cleanable; 43 44 private ZStreamRef (Object owner, LongSupplier addr, LongConsumer end) { 45 this.cleanable = CleanerFactory.cleaner().register(owner, this); 46 this.end = end; 47 this.address = addr.getAsLong(); 48 } 49 50 long address() { 51 return address; 52 } 53 54 void clean() { 55 cleanable.clean(); 56 } 57 58 public synchronized void run() { 59 long addr = address; 60 address = 0; 61 if (addr != 0) { 62 end.accept(addr); 63 } 64 } 65 66 private ZStreamRef (LongSupplier addr, LongConsumer end) { 67 this.cleanable = null; 68 this.end = end; 69 this.address = addr.getAsLong(); 70 } 71 72 /* 73 * If {@code Inflater/Deflater} has been subclassed and the {@code end} method 74 * is overridden, uses {@code finalizer} mechanism for resource cleanup. So 75 * {@code end} method can be called when the {@code Inflater/Deflater} is 76 * unreachable. This mechanism will be removed when the {@code finalize} method 77 * is removed from {@code Inflater/Deflater}. 78 */ 79 static ZStreamRef get(Object owner, LongSupplier addr, LongConsumer end) { 80 Class<?> clz = owner.getClass(); 81 while (clz != Deflater.class && clz != Inflater.class) { 82 try { 83 clz.getDeclaredMethod("end"); 84 return new FinalizableZStreamRef(owner, addr, end); 85 } catch (NoSuchMethodException nsme) {} 86 clz = clz.getSuperclass(); 87 } 88 return new ZStreamRef(owner, addr, end); 89 } 90 91 private static class FinalizableZStreamRef extends ZStreamRef { 92 final Object owner; 93 94 FinalizableZStreamRef (Object owner, LongSupplier addr, LongConsumer end) { 95 super(addr, end); 96 this.owner = owner; 97 } 98 99 @Override 100 void clean() { 101 run(); 102 } 103 104 @Override 105 @SuppressWarnings("deprecation") 106 protected void finalize() { 107 if (owner instanceof Inflater) 108 ((Inflater)owner).end(); 109 else 110 ((Deflater)owner).end(); 111 } 112 } 113 }