< prev index next >

src/java.base/share/classes/java/util/zip/Inflater.java

Print this page
rev 48331 : 8193507: [REDO] Startup regression due to JDK-8185582
Reviewed-by: alanb
Contributed-by: xueming.shen@oracle.com, claes.redestad@oracle.com

*** 23,32 **** --- 23,35 ---- * questions. */ package java.util.zip; + import java.lang.ref.Cleaner.Cleanable; + import jdk.internal.ref.CleanerFactory; + /** * This class provides support for general purpose decompression using the * popular ZLIB compression library. The ZLIB compression library was * initially developed as part of the PNG graphics standard and is not * protected by patents. It is fully described in the specifications at
*** 113,123 **** * library in order to support certain optimizations. * * @param nowrap if true then support GZIP compatible compression */ public Inflater(boolean nowrap) { ! this.zsRef = ZStreamRef.get(this, () -> init(nowrap), Inflater::end); } /** * Creates a new decompressor. */ --- 116,126 ---- * library in order to support certain optimizations. * * @param nowrap if true then support GZIP compatible compression */ public Inflater(boolean nowrap) { ! this.zsRef = ZStreamRef.get(this, init(nowrap)); } /** * Creates a new decompressor. */
*** 426,431 **** --- 429,510 ---- private native int inflateBytes(long addr, byte[] b, int off, int len) throws DataFormatException; private static native int getAdler(long addr); private static native void reset(long addr); private static native void end(long addr); + + /** + * A reference to the native zlib's z_stream structure. It also + * serves as the "cleaner" to clean up the native resource when + * the deflater or infalter is ended, closed or cleaned. + */ + static class ZStreamRef implements Runnable { + + private long address; + private final Cleanable cleanable; + + private ZStreamRef (Inflater owner, long addr) { + this.cleanable = CleanerFactory.cleaner().register(owner, this); + this.address = addr; + } + + long address() { + return address; + } + + void clean() { + cleanable.clean(); + } + + public synchronized void run() { + long addr = address; + address = 0; + if (addr != 0) { + end(addr); + } + } + + private ZStreamRef (long addr) { + this.cleanable = null; + this.address = addr; + } + + /* + * If {@code Inflater} has been subclassed and the {@code end} method is + * overridden, uses {@code finalizer} mechanism for resource cleanup. So + * {@code end} method can be called when the {@code Inflater} is unreachable. + * This mechanism will be removed when the {@code finalize} method is + * removed from {@code Inflater}. + */ + static ZStreamRef get(Inflater owner, long addr) { + Class<?> clz = owner.getClass(); + while (clz != Inflater.class) { + try { + clz.getDeclaredMethod("end"); + return new FinalizableZStreamRef(owner, addr); + } catch (NoSuchMethodException nsme) {} + clz = clz.getSuperclass(); + } + return new ZStreamRef(owner, addr); + } + + private static class FinalizableZStreamRef extends ZStreamRef { + final Inflater owner; + + FinalizableZStreamRef (Inflater owner, long addr) { + super(addr); + this.owner = owner; + } + + @Override + void clean() { + run(); + } + + @Override + @SuppressWarnings("deprecation") + protected void finalize() { + owner.end(); + } + } + } }
< prev index next >