1
1
/*
2
- * Copyright (c) 1996, 2024 , Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 1996, 2025 , Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
49
49
* thrown.
50
50
* <p>
51
51
* This class deflates sequences of bytes into ZLIB compressed data format.
52
- * The input byte sequence is provided in either byte array or byte buffer ,
52
+ * The input byte sequence is provided in either a byte array or a {@link ByteBuffer} ,
53
53
* via one of the {@code setInput()} methods. The output byte sequence is
54
- * written to the output byte array or byte buffer passed to the
54
+ * written to the output byte array or {@code ByteBuffer} passed to the
55
55
* {@code deflate()} methods.
56
56
* <p>
57
- * The following code fragment demonstrates a trivial compression
58
- * and decompression of a string using {@code Deflater} and
59
- * {@code Inflater}.
60
- * {@snippet id="compdecomp" lang="java" class="Snippets" region="DeflaterInflaterExample"}
57
+ * To release the resources used by a {@code Deflater}, an application must close it
58
+ * by invoking its {@link #end()} or {@link #close()} method.
61
59
*
62
60
* @apiNote
63
- * To release resources used by this {@code Deflater}, the {@link #end()} method
64
- * should be called explicitly. Subclasses are responsible for the cleanup of resources
65
- * acquired by the subclass. Subclasses that override {@link #finalize()} in order
66
- * to perform cleanup should be modified to use alternative cleanup mechanisms such
67
- * as {@link java.lang.ref.Cleaner} and remove the overriding {@code finalize} method.
61
+ * This class implements {@link AutoCloseable} to facilitate its usage with
62
+ * {@code try}-with-resources statement. The {@linkplain Deflater#close() close() method} simply
63
+ * calls {@code end()}.
64
+ *
65
+ * <p>
66
+ * The following code fragment demonstrates a trivial compression
67
+ * and decompression of a string using {@code Deflater} and {@code Inflater}.
68
+ * {@snippet id="compdecomp" lang="java" class="Snippets" region="DeflaterInflaterExample"}
68
69
*
69
70
* @see Inflater
70
71
* @author David Connelly
71
72
* @since 1.1
72
73
*/
73
74
74
- public class Deflater {
75
+ public class Deflater implements AutoCloseable {
75
76
76
77
private final DeflaterZStreamRef zsRef ;
77
78
private ByteBuffer input = ZipUtils .defaultBuf ;
@@ -269,6 +270,7 @@ public void setInput(ByteBuffer input) {
269
270
* @param dictionary the dictionary data bytes
270
271
* @param off the start offset of the data
271
272
* @param len the length of the data
273
+ * @throws IllegalStateException if the Deflater is closed
272
274
* @see Inflater#inflate
273
275
* @see Inflater#getAdler()
274
276
*/
@@ -287,6 +289,7 @@ public void setDictionary(byte[] dictionary, int off, int len) {
287
289
* in order to get the Adler-32 value of the dictionary required for
288
290
* decompression.
289
291
* @param dictionary the dictionary data bytes
292
+ * @throws IllegalStateException if the Deflater is closed
290
293
* @see Inflater#inflate
291
294
* @see Inflater#getAdler()
292
295
*/
@@ -305,6 +308,7 @@ public void setDictionary(byte[] dictionary) {
305
308
* return, its position will equal its limit.
306
309
*
307
310
* @param dictionary the dictionary data bytes
311
+ * @throws IllegalStateException if the Deflater is closed
308
312
* @see Inflater#inflate
309
313
* @see Inflater#getAdler()
310
314
*
@@ -437,6 +441,7 @@ public boolean finished() {
437
441
* @param len the maximum number of bytes of compressed data
438
442
* @return the actual number of bytes of compressed data written to the
439
443
* output buffer
444
+ * @throws IllegalStateException if the Deflater is closed
440
445
*/
441
446
public int deflate (byte [] output , int off , int len ) {
442
447
return deflate (output , off , len , NO_FLUSH );
@@ -456,6 +461,7 @@ public int deflate(byte[] output, int off, int len) {
456
461
* @param output the buffer for the compressed data
457
462
* @return the actual number of bytes of compressed data written to the
458
463
* output buffer
464
+ * @throws IllegalStateException if the Deflater is closed
459
465
*/
460
466
public int deflate (byte [] output ) {
461
467
return deflate (output , 0 , output .length , NO_FLUSH );
@@ -476,6 +482,7 @@ public int deflate(byte[] output) {
476
482
* @return the actual number of bytes of compressed data written to the
477
483
* output buffer
478
484
* @throws ReadOnlyBufferException if the given output buffer is read-only
485
+ * @throws IllegalStateException if the Deflater is closed
479
486
* @since 11
480
487
*/
481
488
public int deflate (ByteBuffer output ) {
@@ -531,6 +538,7 @@ public int deflate(ByteBuffer output) {
531
538
* the output buffer
532
539
*
533
540
* @throws IllegalArgumentException if the flush mode is invalid
541
+ * @throws IllegalStateException if the Deflater is closed
534
542
* @since 1.7
535
543
*/
536
544
public int deflate (byte [] output , int off , int len , int flush ) {
@@ -657,6 +665,7 @@ public int deflate(byte[] output, int off, int len, int flush) {
657
665
*
658
666
* @throws IllegalArgumentException if the flush mode is invalid
659
667
* @throws ReadOnlyBufferException if the given output buffer is read-only
668
+ * @throws IllegalStateException if the Deflater is closed
660
669
* @since 11
661
670
*/
662
671
public int deflate (ByteBuffer output , int flush ) {
@@ -783,6 +792,7 @@ public int deflate(ByteBuffer output, int flush) {
783
792
784
793
/**
785
794
* {@return the ADLER-32 value of the uncompressed data}
795
+ * @throws IllegalStateException if the Deflater is closed
786
796
*/
787
797
public int getAdler () {
788
798
synchronized (zsRef ) {
@@ -802,6 +812,7 @@ public int getAdler() {
802
812
* @deprecated Use {@link #getBytesRead()} instead
803
813
*
804
814
* @return the total number of uncompressed bytes input so far
815
+ * @throws IllegalStateException if the Deflater is closed
805
816
*/
806
817
@ Deprecated (since = "23" )
807
818
public int getTotalIn () {
@@ -812,6 +823,7 @@ public int getTotalIn() {
812
823
* Returns the total number of uncompressed bytes input so far.
813
824
*
814
825
* @return the total (non-negative) number of uncompressed bytes input so far
826
+ * @throws IllegalStateException if the Deflater is closed
815
827
* @since 1.5
816
828
*/
817
829
public long getBytesRead () {
@@ -832,6 +844,7 @@ public long getBytesRead() {
832
844
* @deprecated Use {@link #getBytesWritten()} instead
833
845
*
834
846
* @return the total number of compressed bytes output so far
847
+ * @throws IllegalStateException if the Deflater is closed
835
848
*/
836
849
@ Deprecated (since = "23" )
837
850
public int getTotalOut () {
@@ -842,6 +855,7 @@ public int getTotalOut() {
842
855
* Returns the total number of compressed bytes output so far.
843
856
*
844
857
* @return the total (non-negative) number of compressed bytes output so far
858
+ * @throws IllegalStateException if the Deflater is closed
845
859
* @since 1.5
846
860
*/
847
861
public long getBytesWritten () {
@@ -854,6 +868,7 @@ public long getBytesWritten() {
854
868
/**
855
869
* Resets deflater so that a new set of input data can be processed.
856
870
* Keeps current compression level and strategy settings.
871
+ * @throws IllegalStateException if the Deflater is closed
857
872
*/
858
873
public void reset () {
859
874
synchronized (zsRef ) {
@@ -868,23 +883,45 @@ public void reset() {
868
883
}
869
884
870
885
/**
871
- * Closes the compressor and discards any unprocessed input.
886
+ * Closes and releases the resources held by this {@code Deflater}
887
+ * and discards any unprocessed input.
888
+ * <p>
889
+ * If the {@code Deflater} is already closed then invoking this method has no effect.
890
+ *
891
+ * @implSpec Subclasses should override this method to clean up the resources
892
+ * acquired by the subclass.
872
893
*
873
- * This method should be called when the compressor is no longer
874
- * being used. Once this method is called, the behavior of the
875
- * Deflater object is undefined.
894
+ * @see #close()
876
895
*/
877
896
public void end () {
878
897
synchronized (zsRef ) {
898
+ // check if already closed
899
+ if (zsRef .address () == 0 ) {
900
+ return ;
901
+ }
879
902
zsRef .clean ();
880
903
input = ZipUtils .defaultBuf ;
904
+ inputArray = null ;
881
905
}
882
906
}
883
907
908
+ /**
909
+ * Closes and releases the resources held by this {@code Deflater}
910
+ * and discards any unprocessed input.
911
+ *
912
+ * @implSpec This method calls the {@link #end()} method.
913
+ * @since 25
914
+ */
915
+ @ Override
916
+ public void close () {
917
+ end ();
918
+ }
919
+
884
920
private void ensureOpen () {
885
921
assert Thread .holdsLock (zsRef );
886
- if (zsRef .address () == 0 )
887
- throw new NullPointerException ("Deflater has been closed" );
922
+ if (zsRef .address () == 0 ) {
923
+ throw new IllegalStateException ("Deflater has been closed" );
924
+ }
888
925
}
889
926
890
927
/**
@@ -928,10 +965,11 @@ private native long deflateBufferBuffer(long addr,
928
965
*/
929
966
static class DeflaterZStreamRef implements Runnable {
930
967
931
- private long address ;
968
+ private long address ; // will be a non-zero value when the native resource is in use
932
969
private final Cleanable cleanable ;
933
970
934
971
private DeflaterZStreamRef (Deflater owner , long addr ) {
972
+ assert addr != 0 : "native address is 0" ;
935
973
this .cleanable = (owner != null ) ? CleanerFactory .cleaner ().register (owner , this ) : null ;
936
974
this .address = addr ;
937
975
}
0 commit comments