< prev index next >

src/java.base/share/classes/java/util/zip/Deflater.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 compression 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
*** 182,193 **** */ public Deflater(int level, boolean nowrap) { this.level = level; this.strategy = DEFAULT_STRATEGY; this.zsRef = ZStreamRef.get(this, ! () -> init(level, DEFAULT_STRATEGY, nowrap), ! Deflater::end); } /** * Creates a new compressor using the specified compression level. * Compressed data will be generated in ZLIB format. --- 185,195 ---- */ public Deflater(int level, boolean nowrap) { this.level = level; this.strategy = DEFAULT_STRATEGY; this.zsRef = ZStreamRef.get(this, ! init(level, DEFAULT_STRATEGY, nowrap)); } /** * Creates a new compressor using the specified compression level. * Compressed data will be generated in ZLIB format.
*** 589,594 **** --- 591,672 ---- private native int deflateBytes(long addr, byte[] b, int off, int len, int flush); 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 (Deflater 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 Deflater} 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 Deflater} is unreachable. + * This mechanism will be removed when the {@code finalize} method is + * removed from {@code Deflater}. + */ + static ZStreamRef get(Deflater owner, long addr) { + Class<?> clz = owner.getClass(); + while (clz != Deflater.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 Deflater owner; + + FinalizableZStreamRef (Deflater owner, long addr) { + super(addr); + this.owner = owner; + } + + @Override + void clean() { + run(); + } + + @Override + @SuppressWarnings("deprecation") + protected void finalize() { + owner.end(); + } + } + } }
< prev index next >