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 decompression using the |
32 * This class provides support for general purpose decompression 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 * |
89 * |
87 */ |
90 */ |
88 |
91 |
89 public class Inflater { |
92 public class Inflater { |
90 |
93 |
91 private final ZStreamRef zsRef; |
94 private final InflaterZStreamRef zsRef; |
92 private byte[] buf = defaultBuf; |
95 private byte[] buf = defaultBuf; |
93 private int off, len; |
96 private int off, len; |
94 private boolean finished; |
97 private boolean finished; |
95 private boolean needDict; |
98 private boolean needDict; |
96 private long bytesRead; |
99 private long bytesRead; |
113 * library in order to support certain optimizations. |
116 * library in order to support certain optimizations. |
114 * |
117 * |
115 * @param nowrap if true then support GZIP compatible compression |
118 * @param nowrap if true then support GZIP compatible compression |
116 */ |
119 */ |
117 public Inflater(boolean nowrap) { |
120 public Inflater(boolean nowrap) { |
118 this.zsRef = ZStreamRef.get(this, () -> init(nowrap), Inflater::end); |
121 this.zsRef = InflaterZStreamRef.get(this, init(nowrap)); |
119 } |
122 } |
120 |
123 |
121 /** |
124 /** |
122 * Creates a new decompressor. |
125 * Creates a new decompressor. |
123 */ |
126 */ |
426 private native int inflateBytes(long addr, byte[] b, int off, int len) |
429 private native int inflateBytes(long addr, byte[] b, int off, int len) |
427 throws DataFormatException; |
430 throws DataFormatException; |
428 private static native int getAdler(long addr); |
431 private static native int getAdler(long addr); |
429 private static native void reset(long addr); |
432 private static native void reset(long addr); |
430 private static native void end(long addr); |
433 private static native void end(long addr); |
|
434 |
|
435 /** |
|
436 * A reference to the native zlib's z_stream structure. It also |
|
437 * serves as the "cleaner" to clean up the native resource when |
|
438 * the Inflater is ended, closed or cleaned. |
|
439 */ |
|
440 static class InflaterZStreamRef implements Runnable { |
|
441 |
|
442 private long address; |
|
443 private final Cleanable cleanable; |
|
444 |
|
445 private InflaterZStreamRef(Inflater owner, long addr) { |
|
446 this.cleanable = (owner != null) ? CleanerFactory.cleaner().register(owner, this) : null; |
|
447 this.address = addr; |
|
448 } |
|
449 |
|
450 long address() { |
|
451 return address; |
|
452 } |
|
453 |
|
454 void clean() { |
|
455 cleanable.clean(); |
|
456 } |
|
457 |
|
458 public synchronized void run() { |
|
459 long addr = address; |
|
460 address = 0; |
|
461 if (addr != 0) { |
|
462 end(addr); |
|
463 } |
|
464 } |
|
465 |
|
466 /* |
|
467 * If {@code Inflater} has been subclassed and the {@code end} method is |
|
468 * overridden, uses {@code finalizer} mechanism for resource cleanup. So |
|
469 * {@code end} method can be called when the {@code Inflater} is unreachable. |
|
470 * This mechanism will be removed when the {@code finalize} method is |
|
471 * removed from {@code Inflater}. |
|
472 */ |
|
473 static InflaterZStreamRef get(Inflater owner, long addr) { |
|
474 Class<?> clz = owner.getClass(); |
|
475 while (clz != Inflater.class) { |
|
476 try { |
|
477 clz.getDeclaredMethod("end"); |
|
478 return new FinalizableZStreamRef(owner, addr); |
|
479 } catch (NoSuchMethodException nsme) {} |
|
480 clz = clz.getSuperclass(); |
|
481 } |
|
482 return new InflaterZStreamRef(owner, addr); |
|
483 } |
|
484 |
|
485 private static class FinalizableZStreamRef extends InflaterZStreamRef { |
|
486 final Inflater owner; |
|
487 |
|
488 FinalizableZStreamRef(Inflater owner, long addr) { |
|
489 super(null, addr); |
|
490 this.owner = owner; |
|
491 } |
|
492 |
|
493 @Override |
|
494 void clean() { |
|
495 run(); |
|
496 } |
|
497 |
|
498 @Override |
|
499 @SuppressWarnings("deprecation") |
|
500 protected void finalize() { |
|
501 owner.end(); |
|
502 } |
|
503 } |
|
504 } |
431 } |
505 } |