22 * or visit www.oracle.com if you need additional information or have any |
22 * or visit www.oracle.com if you need additional information or have any |
23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package java.util.zip; |
26 package java.util.zip; |
|
27 |
|
28 import java.lang.ref.Cleaner.Cleanable; |
|
29 import jdk.internal.ref.CleanerFactory; |
27 |
30 |
28 /** |
31 /** |
29 * This class provides support for general purpose compression using the |
32 * This class provides support for general purpose compression using the |
30 * popular ZLIB compression library. The ZLIB compression library was |
33 * popular ZLIB compression library. The ZLIB compression library was |
31 * initially developed as part of the PNG graphics standard and is not |
34 * initially developed as part of the PNG graphics standard and is not |
86 * @since 1.1 |
89 * @since 1.1 |
87 */ |
90 */ |
88 |
91 |
89 public class Deflater { |
92 public class Deflater { |
90 |
93 |
91 private final ZStreamRef zsRef; |
94 private final DeflaterZStreamRef zsRef; |
92 private byte[] buf = new byte[0]; |
95 private byte[] buf = new byte[0]; |
93 private int off, len; |
96 private int off, len; |
94 private int level, strategy; |
97 private int level, strategy; |
95 private boolean setParams; |
98 private boolean setParams; |
96 private boolean finish, finished; |
99 private boolean finish, finished; |
181 * @param nowrap if true then use GZIP compatible compression |
184 * @param nowrap if true then use GZIP compatible compression |
182 */ |
185 */ |
183 public Deflater(int level, boolean nowrap) { |
186 public Deflater(int level, boolean nowrap) { |
184 this.level = level; |
187 this.level = level; |
185 this.strategy = DEFAULT_STRATEGY; |
188 this.strategy = DEFAULT_STRATEGY; |
186 this.zsRef = ZStreamRef.get(this, |
189 this.zsRef = DeflaterZStreamRef.get(this, |
187 () -> init(level, DEFAULT_STRATEGY, nowrap), |
190 init(level, DEFAULT_STRATEGY, nowrap)); |
188 Deflater::end); |
|
189 } |
191 } |
190 |
192 |
191 /** |
193 /** |
192 * Creates a new compressor using the specified compression level. |
194 * Creates a new compressor using the specified compression level. |
193 * Compressed data will be generated in ZLIB format. |
195 * Compressed data will be generated in ZLIB format. |
589 private native int deflateBytes(long addr, byte[] b, int off, int len, |
591 private native int deflateBytes(long addr, byte[] b, int off, int len, |
590 int flush); |
592 int flush); |
591 private static native int getAdler(long addr); |
593 private static native int getAdler(long addr); |
592 private static native void reset(long addr); |
594 private static native void reset(long addr); |
593 private static native void end(long addr); |
595 private static native void end(long addr); |
|
596 |
|
597 /** |
|
598 * A reference to the native zlib's z_stream structure. It also |
|
599 * serves as the "cleaner" to clean up the native resource when |
|
600 * the Deflater is ended, closed or cleaned. |
|
601 */ |
|
602 static class DeflaterZStreamRef implements Runnable { |
|
603 |
|
604 private long address; |
|
605 private final Cleanable cleanable; |
|
606 |
|
607 private DeflaterZStreamRef(Deflater owner, long addr) { |
|
608 this.cleanable = (owner != null) ? CleanerFactory.cleaner().register(owner, this) : null; |
|
609 this.address = addr; |
|
610 } |
|
611 |
|
612 long address() { |
|
613 return address; |
|
614 } |
|
615 |
|
616 void clean() { |
|
617 cleanable.clean(); |
|
618 } |
|
619 |
|
620 public synchronized void run() { |
|
621 long addr = address; |
|
622 address = 0; |
|
623 if (addr != 0) { |
|
624 end(addr); |
|
625 } |
|
626 } |
|
627 |
|
628 /* |
|
629 * If {@code Deflater} has been subclassed and the {@code end} method is |
|
630 * overridden, uses {@code finalizer} mechanism for resource cleanup. So |
|
631 * {@code end} method can be called when the {@code Deflater} is unreachable. |
|
632 * This mechanism will be removed when the {@code finalize} method is |
|
633 * removed from {@code Deflater}. |
|
634 */ |
|
635 static DeflaterZStreamRef get(Deflater owner, long addr) { |
|
636 Class<?> clz = owner.getClass(); |
|
637 while (clz != Deflater.class) { |
|
638 try { |
|
639 clz.getDeclaredMethod("end"); |
|
640 return new FinalizableZStreamRef(owner, addr); |
|
641 } catch (NoSuchMethodException nsme) {} |
|
642 clz = clz.getSuperclass(); |
|
643 } |
|
644 return new DeflaterZStreamRef(owner, addr); |
|
645 } |
|
646 |
|
647 private static class FinalizableZStreamRef extends DeflaterZStreamRef { |
|
648 final Deflater owner; |
|
649 |
|
650 FinalizableZStreamRef (Deflater owner, long addr) { |
|
651 super(null, addr); |
|
652 this.owner = owner; |
|
653 } |
|
654 |
|
655 @Override |
|
656 void clean() { |
|
657 run(); |
|
658 } |
|
659 |
|
660 @Override |
|
661 @SuppressWarnings("deprecation") |
|
662 protected void finalize() { |
|
663 owner.end(); |
|
664 } |
|
665 } |
|
666 } |
594 } |
667 } |