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

Print this page


   1 /*
   2  * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.util.zip;
  27 
  28 import java.lang.ref.Cleaner.Cleanable;





  29 import jdk.internal.ref.CleanerFactory;

  30 
  31 /**
  32  * This class provides support for general purpose decompression using the
  33  * popular ZLIB compression library. The ZLIB compression library was
  34  * initially developed as part of the PNG graphics standard and is not
  35  * protected by patents. It is fully described in the specifications at
  36  * the <a href="package-summary.html#package.description">java.util.zip
  37  * package description</a>.
  38  *
  39  * <p>The following code fragment demonstrates a trivial compression





  40  * and decompression of a string using {@code Deflater} and
  41  * {@code Inflater}.
  42  *
  43  * <blockquote><pre>
  44  * try {
  45  *     // Encode a String into bytes
  46  *     String inputString = "blahblahblah\u20AC\u20AC";
  47  *     byte[] input = inputString.getBytes("UTF-8");
  48  *
  49  *     // Compress the bytes
  50  *     byte[] output = new byte[100];
  51  *     Deflater compresser = new Deflater();
  52  *     compresser.setInput(input);
  53  *     compresser.finish();
  54  *     int compressedDataLength = compresser.deflate(output);
  55  *
  56  *     // Decompress the bytes
  57  *     Inflater decompresser = new Inflater();
  58  *     decompresser.setInput(output, 0, compressedDataLength);
  59  *     byte[] result = new byte[100];


  75  * acquired by the subclass. Subclasses that override {@link #finalize()} in order
  76  * to perform cleanup should be modified to use alternative cleanup mechanisms such
  77  * as {@link java.lang.ref.Cleaner} and remove the overriding {@code finalize} method.
  78  *
  79  * @implSpec
  80  * If this {@code Inflater} has been subclassed and the {@code end} method has been
  81  * overridden, the {@code end} method will be called by the finalization when the
  82  * inflater is unreachable. But the subclasses should not depend on this specific
  83  * implementation; the finalization is not reliable and the {@code finalize} method
  84  * is deprecated to be removed.
  85  *
  86  * @see         Deflater
  87  * @author      David Connelly
  88  * @since 1.1
  89  *
  90  */
  91 
  92 public class Inflater {
  93 
  94     private final InflaterZStreamRef zsRef;
  95     private byte[] buf = defaultBuf;
  96     private int off, len;

  97     private boolean finished;
  98     private boolean needDict;
  99     private long bytesRead;
 100     private long bytesWritten;
 101 
 102     private static final byte[] defaultBuf = new byte[0];





 103 
 104     static {
 105         ZipUtils.loadLibrary();
 106         initIDs();
 107     }
 108 
 109     /**
 110      * Creates a new decompressor. If the parameter 'nowrap' is true then
 111      * the ZLIB header and checksum fields will not be used. This provides
 112      * compatibility with the compression format used by both GZIP and PKZIP.
 113      * <p>
 114      * Note: When using the 'nowrap' option it is also necessary to provide
 115      * an extra "dummy" byte as input. This is required by the ZLIB native
 116      * library in order to support certain optimizations.
 117      *
 118      * @param nowrap if true then support GZIP compatible compression
 119      */
 120     public Inflater(boolean nowrap) {
 121         this.zsRef = InflaterZStreamRef.get(this, init(nowrap));
 122     }
 123 
 124     /**
 125      * Creates a new decompressor.
 126      */
 127     public Inflater() {
 128         this(false);
 129     }
 130 
 131     /**
 132      * Sets input data for decompression. Should be called whenever
 133      * needsInput() returns true indicating that more input data is
 134      * required.
 135      * @param b the input data bytes



 136      * @param off the start offset of the input data
 137      * @param len the length of the input data
 138      * @see Inflater#needsInput
 139      */
 140     public void setInput(byte[] b, int off, int len) {
 141         if (b == null) {
 142             throw new NullPointerException();
 143         }
 144         if (off < 0 || len < 0 || off > b.length - len) {
 145             throw new ArrayIndexOutOfBoundsException();
 146         }
 147         synchronized (zsRef) {
 148             this.buf = b;
 149             this.off = off;
 150             this.len = len;

 151         }
 152     }
 153 
 154     /**
 155      * Sets input data for decompression. Should be called whenever
 156      * needsInput() returns true indicating that more input data is
 157      * required.
 158      * @param b the input data bytes




























 159      * @see Inflater#needsInput

 160      */
 161     public void setInput(byte[] b) {
 162         setInput(b, 0, b.length);




 163     }
 164 
 165     /**
 166      * Sets the preset dictionary to the given array of bytes. Should be
 167      * called when inflate() returns 0 and needsDictionary() returns true
 168      * indicating that a preset dictionary is required. The method getAdler()
 169      * can be used to get the Adler-32 value of the dictionary needed.
 170      * @param b the dictionary data bytes
 171      * @param off the start offset of the data
 172      * @param len the length of the data
 173      * @see Inflater#needsDictionary
 174      * @see Inflater#getAdler
 175      */
 176     public void setDictionary(byte[] b, int off, int len) {
 177         if (b == null) {
 178             throw new NullPointerException();
 179         }
 180         if (off < 0 || len < 0 || off > b.length - len) {
 181             throw new ArrayIndexOutOfBoundsException();
 182         }
 183         synchronized (zsRef) {
 184             ensureOpen();
 185             setDictionary(zsRef.address(), b, off, len);
 186             needDict = false;
 187         }
 188     }
 189 
 190     /**
 191      * Sets the preset dictionary to the given array of bytes. Should be
 192      * called when inflate() returns 0 and needsDictionary() returns true
 193      * indicating that a preset dictionary is required. The method getAdler()
 194      * can be used to get the Adler-32 value of the dictionary needed.
 195      * @param b the dictionary data bytes
 196      * @see Inflater#needsDictionary
 197      * @see Inflater#getAdler
 198      */
 199     public void setDictionary(byte[] b) {
 200         setDictionary(b, 0, b.length);




































 201     }
 202 
 203     /**
 204      * Returns the total number of bytes remaining in the input buffer.
 205      * This can be used to find out what bytes still remain in the input
 206      * buffer after decompression has finished.
 207      * @return the total number of bytes remaining in the input buffer
 208      */
 209     public int getRemaining() {
 210         synchronized (zsRef) {
 211             return len;

 212         }
 213     }
 214 
 215     /**
 216      * Returns true if no data remains in the input buffer. This can
 217      * be used to determine if #setInput should be called in order
 218      * to provide more input.

 219      * @return true if no data remains in the input buffer
 220      */
 221     public boolean needsInput() {
 222         synchronized (zsRef) {
 223             return len <= 0;

 224         }
 225     }
 226 
 227     /**
 228      * Returns true if a preset dictionary is needed for decompression.
 229      * @return true if a preset dictionary is needed for decompression
 230      * @see Inflater#setDictionary
 231      */
 232     public boolean needsDictionary() {
 233         synchronized (zsRef) {
 234             return needDict;
 235         }
 236     }
 237 
 238     /**
 239      * Returns true if the end of the compressed data stream has been
 240      * reached.
 241      * @return true if the end of the compressed data stream has been
 242      * reached
 243      */
 244     public boolean finished() {
 245         synchronized (zsRef) {
 246             return finished;
 247         }
 248     }
 249 
 250     /**
 251      * Uncompresses bytes into specified buffer. Returns actual number
 252      * of bytes uncompressed. A return value of 0 indicates that
 253      * needsInput() or needsDictionary() should be called in order to
 254      * determine if more input data or a preset dictionary is required.
 255      * In the latter case, getAdler() can be used to get the Adler-32
 256      * value of the dictionary required.
 257      * @param b the buffer for the uncompressed data


















 258      * @param off the start offset of the data
 259      * @param len the maximum number of uncompressed bytes
 260      * @return the actual number of uncompressed bytes
 261      * @exception DataFormatException if the compressed data format is invalid
 262      * @see Inflater#needsInput
 263      * @see Inflater#needsDictionary
 264      */
 265     public int inflate(byte[] b, int off, int len)
 266         throws DataFormatException
 267     {
 268         if (b == null) {
 269             throw new NullPointerException();
 270         }
 271         if (off < 0 || len < 0 || off > b.length - len) {
 272             throw new ArrayIndexOutOfBoundsException();
 273         }
 274         synchronized (zsRef) {
 275             ensureOpen();
 276             int thisLen = this.len;
 277             int n = inflateBytes(zsRef.address(), b, off, len);
 278             bytesWritten += n;
 279             bytesRead += (thisLen - this.len);
 280             return n;


























































 281         }
 282     }
 283 
 284     /**
 285      * Uncompresses bytes into specified buffer. Returns actual number
 286      * of bytes uncompressed. A return value of 0 indicates that
 287      * needsInput() or needsDictionary() should be called in order to
 288      * determine if more input data or a preset dictionary is required.
 289      * In the latter case, getAdler() can be used to get the Adler-32
 290      * value of the dictionary required.
 291      * @param b the buffer for the uncompressed data













 292      * @return the actual number of uncompressed bytes
 293      * @exception DataFormatException if the compressed data format is invalid
 294      * @see Inflater#needsInput
 295      * @see Inflater#needsDictionary
 296      */
 297     public int inflate(byte[] b) throws DataFormatException {
 298         return inflate(b, 0, b.length);






















































































































































 299     }
 300 
 301     /**
 302      * Returns the ADLER-32 value of the uncompressed data.
 303      * @return the ADLER-32 value of the uncompressed data
 304      */
 305     public int getAdler() {
 306         synchronized (zsRef) {
 307             ensureOpen();
 308             return getAdler(zsRef.address());
 309         }
 310     }
 311 
 312     /**
 313      * Returns the total number of compressed bytes input so far.
 314      *
 315      * <p>Since the number of bytes may be greater than
 316      * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
 317      * the preferred means of obtaining this information.</p>
 318      *


 351     /**
 352      * Returns the total number of uncompressed bytes output so far.
 353      *
 354      * @return the total (non-negative) number of uncompressed bytes output so far
 355      * @since 1.5
 356      */
 357     public long getBytesWritten() {
 358         synchronized (zsRef) {
 359             ensureOpen();
 360             return bytesWritten;
 361         }
 362     }
 363 
 364     /**
 365      * Resets inflater so that a new set of input data can be processed.
 366      */
 367     public void reset() {
 368         synchronized (zsRef) {
 369             ensureOpen();
 370             reset(zsRef.address());
 371             buf = defaultBuf;

 372             finished = false;
 373             needDict = false;
 374             off = len = 0;
 375             bytesRead = bytesWritten = 0;
 376         }
 377     }
 378 
 379     /**
 380      * Closes the decompressor and discards any unprocessed input.
 381      *
 382      * This method should be called when the decompressor is no longer
 383      * being used. Once this method is called, the behavior of the
 384      * Inflater object is undefined.
 385      */
 386     public void end() {
 387         synchronized (zsRef) {
 388             zsRef.clean();
 389             buf = null;

 390         }
 391     }
 392 
 393     /**
 394      * Closes the decompressor when garbage is collected.
 395      *
 396      * @implSpec
 397      * If this {@code Inflater} has been subclassed and the {@code end} method
 398      * has been overridden, the {@code end} method will be called when the
 399      * inflater is unreachable.
 400      *
 401      * @deprecated The {@code finalize} method has been deprecated and will be
 402      *     removed. It is implemented as a no-op. Subclasses that override
 403      *     {@code finalize} in order to perform cleanup should be modified to use
 404      *     alternative cleanup mechanisms and remove the overriding {@code finalize}
 405      *     method. The recommended cleanup for compressor is to explicitly call
 406      *     {@code end} method when it is no longer in use. If the {@code end} is
 407      *     not invoked explicitly the resource of the compressor will be released
 408      *     when the instance becomes unreachable,
 409      */
 410     @Deprecated(since="9", forRemoval=true)
 411     protected void finalize() {}
 412 
 413     private void ensureOpen () {
 414         assert Thread.holdsLock(zsRef);
 415         if (zsRef.address() == 0)
 416             throw new NullPointerException("Inflater has been closed");
 417     }
 418 
 419     boolean ended() {
 420         synchronized (zsRef) {
 421             return zsRef.address() == 0;
 422         }
 423     }
 424 
 425     private static native void initIDs();
 426     private static native long init(boolean nowrap);
 427     private static native void setDictionary(long addr, byte[] b, int off,
 428                                              int len);
 429     private native int inflateBytes(long addr, byte[] b, int off, int len)
 430             throws DataFormatException;











 431     private static native int getAdler(long addr);
 432     private static native void reset(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() {


   1 /*
   2  * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.util.zip;
  27 
  28 import java.lang.ref.Cleaner.Cleanable;
  29 import java.lang.ref.Reference;
  30 import java.nio.ByteBuffer;
  31 import java.nio.ReadOnlyBufferException;
  32 import java.util.Objects;
  33 
  34 import jdk.internal.ref.CleanerFactory;
  35 import sun.nio.ch.DirectBuffer;
  36 
  37 /**
  38  * This class provides support for general purpose decompression using the
  39  * popular ZLIB compression library. The ZLIB compression library was
  40  * initially developed as part of the PNG graphics standard and is not
  41  * protected by patents. It is fully described in the specifications at
  42  * the <a href="package-summary.html#package.description">java.util.zip
  43  * package description</a>.
  44  * <p>
  45  * This class inflates sequences of ZLIB compressed bytes. The input byte
  46  * sequence is provided in either byte array or byte buffer, via one of the
  47  * {@code setInput()} methods. The output byte sequence is written to the
  48  * output byte array or byte buffer passed to the {@code deflate()} methods.
  49  * <p>
  50  * The following code fragment demonstrates a trivial compression
  51  * and decompression of a string using {@code Deflater} and
  52  * {@code Inflater}.
  53  *
  54  * <blockquote><pre>
  55  * try {
  56  *     // Encode a String into bytes
  57  *     String inputString = "blahblahblah\u20AC\u20AC";
  58  *     byte[] input = inputString.getBytes("UTF-8");
  59  *
  60  *     // Compress the bytes
  61  *     byte[] output = new byte[100];
  62  *     Deflater compresser = new Deflater();
  63  *     compresser.setInput(input);
  64  *     compresser.finish();
  65  *     int compressedDataLength = compresser.deflate(output);
  66  *
  67  *     // Decompress the bytes
  68  *     Inflater decompresser = new Inflater();
  69  *     decompresser.setInput(output, 0, compressedDataLength);
  70  *     byte[] result = new byte[100];


  86  * acquired by the subclass. Subclasses that override {@link #finalize()} in order
  87  * to perform cleanup should be modified to use alternative cleanup mechanisms such
  88  * as {@link java.lang.ref.Cleaner} and remove the overriding {@code finalize} method.
  89  *
  90  * @implSpec
  91  * If this {@code Inflater} has been subclassed and the {@code end} method has been
  92  * overridden, the {@code end} method will be called by the finalization when the
  93  * inflater is unreachable. But the subclasses should not depend on this specific
  94  * implementation; the finalization is not reliable and the {@code finalize} method
  95  * is deprecated to be removed.
  96  *
  97  * @see         Deflater
  98  * @author      David Connelly
  99  * @since 1.1
 100  *
 101  */
 102 
 103 public class Inflater {
 104 
 105     private final InflaterZStreamRef zsRef;
 106     private ByteBuffer input = ZipUtils.defaultBuf;
 107     private byte[] inputArray;
 108     private int inputPos, inputLim;
 109     private boolean finished;
 110     private boolean needDict;
 111     private long bytesRead;
 112     private long bytesWritten;
 113 
 114     /*
 115      * These fields are used as an "out" parameter from JNI when a
 116      * DataFormatException is thrown during the inflate operation.
 117      */
 118     private int inputConsumed;
 119     private int outputConsumed;
 120 
 121     static {
 122         ZipUtils.loadLibrary();
 123         initIDs();
 124     }
 125 
 126     /**
 127      * Creates a new decompressor. If the parameter 'nowrap' is true then
 128      * the ZLIB header and checksum fields will not be used. This provides
 129      * compatibility with the compression format used by both GZIP and PKZIP.
 130      * <p>
 131      * Note: When using the 'nowrap' option it is also necessary to provide
 132      * an extra "dummy" byte as input. This is required by the ZLIB native
 133      * library in order to support certain optimizations.
 134      *
 135      * @param nowrap if true then support GZIP compatible compression
 136      */
 137     public Inflater(boolean nowrap) {
 138         this.zsRef = InflaterZStreamRef.get(this, init(nowrap));
 139     }
 140 
 141     /**
 142      * Creates a new decompressor.
 143      */
 144     public Inflater() {
 145         this(false);
 146     }
 147 
 148     /**
 149      * Sets input data for decompression.
 150      * <p>
 151      * One of the {@code setInput()} methods should be called whenever
 152      * {@code needsInput()} returns true indicating that more input data
 153      * is required.
 154      *
 155      * @param input the input data bytes
 156      * @param off the start offset of the input data
 157      * @param len the length of the input data
 158      * @see Inflater#needsInput
 159      */
 160     public void setInput(byte[] input, int off, int len) {
 161         if (off < 0 || len < 0 || off > input.length - len) {



 162             throw new ArrayIndexOutOfBoundsException();
 163         }
 164         synchronized (zsRef) {
 165             this.input = null;
 166             this.inputArray = input;
 167             this.inputPos = off;
 168             this.inputLim = off + len;
 169         }
 170     }
 171 
 172     /**
 173      * Sets input data for decompression.
 174      * <p>
 175      * One of the {@code setInput()} methods should be called whenever
 176      * {@code needsInput()} returns true indicating that more input data
 177      * is required.
 178      *
 179      * @param input the input data bytes
 180      * @see Inflater#needsInput
 181      */
 182     public void setInput(byte[] input) {
 183         setInput(input, 0, input.length);
 184     }
 185 
 186     /**
 187      * Sets input data for decompression.
 188      * <p>
 189      * One of the {@code setInput()} methods should be called whenever
 190      * {@code needsInput()} returns true indicating that more input data
 191      * is required.
 192      * <p>
 193      * The given buffer's position will be advanced as inflate
 194      * operations are performed, up to the buffer's limit.
 195      * The input buffer may be modified (refilled) between inflate
 196      * operations; doing so is equivalent to creating a new buffer
 197      * and setting it with this method.
 198      * <p>
 199      * Modifying the input buffer's contents, position, or limit
 200      * concurrently with an inflate operation will result in
 201      * undefined behavior, which may include incorrect operation
 202      * results or operation failure.
 203      *
 204      * @param input the input data bytes
 205      * @see Inflater#needsInput
 206      * @since 11
 207      */
 208     public void setInput(ByteBuffer input) {
 209         Objects.requireNonNull(input);
 210         synchronized (zsRef) {
 211             this.input = input;
 212             this.inputArray = null;
 213         }
 214     }
 215 
 216     /**
 217      * Sets the preset dictionary to the given array of bytes. Should be
 218      * called when inflate() returns 0 and needsDictionary() returns true
 219      * indicating that a preset dictionary is required. The method getAdler()
 220      * can be used to get the Adler-32 value of the dictionary needed.
 221      * @param dictionary the dictionary data bytes
 222      * @param off the start offset of the data
 223      * @param len the length of the data
 224      * @see Inflater#needsDictionary
 225      * @see Inflater#getAdler
 226      */
 227     public void setDictionary(byte[] dictionary, int off, int len) {
 228         if (off < 0 || len < 0 || off > dictionary.length - len) {



 229             throw new ArrayIndexOutOfBoundsException();
 230         }
 231         synchronized (zsRef) {
 232             ensureOpen();
 233             setDictionary(zsRef.address(), dictionary, off, len);
 234             needDict = false;
 235         }
 236     }
 237 
 238     /**
 239      * Sets the preset dictionary to the given array of bytes. Should be
 240      * called when inflate() returns 0 and needsDictionary() returns true
 241      * indicating that a preset dictionary is required. The method getAdler()
 242      * can be used to get the Adler-32 value of the dictionary needed.
 243      * @param dictionary the dictionary data bytes
 244      * @see Inflater#needsDictionary
 245      * @see Inflater#getAdler
 246      */
 247     public void setDictionary(byte[] dictionary) {
 248         setDictionary(dictionary, 0, dictionary.length);
 249     }
 250 
 251     /**
 252      * Sets the preset dictionary to the bytes in the given buffer. Should be
 253      * called when inflate() returns 0 and needsDictionary() returns true
 254      * indicating that a preset dictionary is required. The method getAdler()
 255      * can be used to get the Adler-32 value of the dictionary needed.
 256      * <p>
 257      * The bytes in given byte buffer will be fully consumed by this method.  On
 258      * return, its position will equal its limit.
 259      *
 260      * @param dictionary the dictionary data bytes
 261      * @see Inflater#needsDictionary
 262      * @see Inflater#getAdler
 263      * @since 11
 264      */
 265     public void setDictionary(ByteBuffer dictionary) {
 266         synchronized (zsRef) {
 267             int position = dictionary.position();
 268             int remaining = Math.max(dictionary.limit() - position, 0);
 269             ensureOpen();
 270             if (dictionary.isDirect()) {
 271                 long address = ((DirectBuffer) dictionary).address();
 272                 try {
 273                     setDictionaryBuffer(zsRef.address(), address + position, remaining);
 274                 } finally {
 275                     Reference.reachabilityFence(dictionary);
 276                 }
 277             } else {
 278                 byte[] array = ZipUtils.getBufferArray(dictionary);
 279                 int offset = ZipUtils.getBufferOffset(dictionary);
 280                 setDictionary(zsRef.address(), array, offset + position, remaining);
 281             }
 282             dictionary.position(position + remaining);
 283             needDict = false;
 284         }
 285     }
 286 
 287     /**
 288      * Returns the total number of bytes remaining in the input buffer.
 289      * This can be used to find out what bytes still remain in the input
 290      * buffer after decompression has finished.
 291      * @return the total number of bytes remaining in the input buffer
 292      */
 293     public int getRemaining() {
 294         synchronized (zsRef) {
 295             ByteBuffer input = this.input;
 296             return input == null ? inputLim - inputPos : input.remaining();
 297         }
 298     }
 299 
 300     /**
 301      * Returns true if no data remains in the input buffer. This can
 302      * be used to determine if one of the {@code setInput()} methods should be
 303      * called in order to provide more input.
 304      *
 305      * @return true if no data remains in the input buffer
 306      */
 307     public boolean needsInput() {
 308         synchronized (zsRef) {
 309             ByteBuffer input = this.input;
 310             return input == null ? inputLim == inputPos : ! input.hasRemaining();
 311         }
 312     }
 313 
 314     /**
 315      * Returns true if a preset dictionary is needed for decompression.
 316      * @return true if a preset dictionary is needed for decompression
 317      * @see Inflater#setDictionary
 318      */
 319     public boolean needsDictionary() {
 320         synchronized (zsRef) {
 321             return needDict;
 322         }
 323     }
 324 
 325     /**
 326      * Returns true if the end of the compressed data stream has been
 327      * reached.
 328      * @return true if the end of the compressed data stream has been
 329      * reached
 330      */
 331     public boolean finished() {
 332         synchronized (zsRef) {
 333             return finished;
 334         }
 335     }
 336 
 337     /**
 338      * Uncompresses bytes into specified buffer. Returns actual number
 339      * of bytes uncompressed. A return value of 0 indicates that
 340      * needsInput() or needsDictionary() should be called in order to
 341      * determine if more input data or a preset dictionary is required.
 342      * In the latter case, getAdler() can be used to get the Adler-32
 343      * value of the dictionary required.
 344      * <p>
 345      * If the {@link #setInput(ByteBuffer)} method was called to provide a buffer
 346      * for input, the input buffer's position will be advanced by the number of bytes
 347      * consumed by this operation, even in the event that a {@link DataFormatException}
 348      * is thrown.
 349      * <p>
 350      * The {@linkplain #getRemaining() remaining byte count} will be reduced by
 351      * the number of consumed input bytes.  If the {@link #setInput(ByteBuffer)}
 352      * method was called to provide a buffer for input, the input buffer's position
 353      * will be advanced the number of consumed bytes.
 354      * <p>
 355      * These byte totals, as well as
 356      * the {@linkplain #getBytesRead() total bytes read}
 357      * and the {@linkplain #getBytesWritten() total bytes written}
 358      * values, will be updated even in the event that a {@link DataFormatException}
 359      * is thrown to reflect the amount of data consumed and produced before the
 360      * exception occurred.
 361      *
 362      * @param output the buffer for the uncompressed data
 363      * @param off the start offset of the data
 364      * @param len the maximum number of uncompressed bytes
 365      * @return the actual number of uncompressed bytes
 366      * @throws DataFormatException if the compressed data format is invalid
 367      * @see Inflater#needsInput
 368      * @see Inflater#needsDictionary
 369      */
 370     public int inflate(byte[] output, int off, int len)
 371         throws DataFormatException
 372     {
 373         if (off < 0 || len < 0 || off > output.length - len) {



 374             throw new ArrayIndexOutOfBoundsException();
 375         }
 376         synchronized (zsRef) {
 377             ensureOpen();
 378             ByteBuffer input = this.input;
 379             long result;
 380             int inputPos;
 381             try {
 382                 if (input == null) {
 383                     inputPos = this.inputPos;
 384                     try {
 385                         result = inflateBytesBytes(zsRef.address(),
 386                             inputArray, inputPos, inputLim - inputPos,
 387                             output, off, len);
 388                     } catch (DataFormatException e) {
 389                         this.inputPos = inputPos + inputConsumed;
 390                         throw e;
 391                     }
 392                 } else {
 393                     inputPos = input.position();
 394                     try {
 395                         int inputRem = Math.max(input.limit() - inputPos, 0);
 396                         if (input.isDirect()) {
 397                             try {
 398                                 long inputAddress = ((DirectBuffer) input).address();
 399                                 result = inflateBufferBytes(zsRef.address(),
 400                                     inputAddress + inputPos, inputRem,
 401                                     output, off, len);
 402                             } finally {
 403                                 Reference.reachabilityFence(input);
 404                             }
 405                         } else {
 406                             byte[] inputArray = ZipUtils.getBufferArray(input);
 407                             int inputOffset = ZipUtils.getBufferOffset(input);
 408                             result = inflateBytesBytes(zsRef.address(),
 409                                 inputArray, inputOffset + inputPos, inputRem,
 410                                 output, off, len);
 411                         }
 412                     } catch (DataFormatException e) {
 413                         input.position(inputPos + inputConsumed);
 414                         throw e;
 415                     }
 416                 }
 417             } catch (DataFormatException e) {
 418                 bytesRead += inputConsumed;
 419                 inputConsumed = 0;
 420                 int written = outputConsumed;
 421                 bytesWritten += written;
 422                 outputConsumed = 0;
 423                 throw e;
 424             }
 425             int read = (int) (result & 0x7fff_ffffL);
 426             int written = (int) (result >>> 31 & 0x7fff_ffffL);
 427             if ((result >>> 62 & 1) != 0) {
 428                 finished = true;
 429             }
 430             if ((result >>> 63 & 1) != 0) {
 431                 needDict = true;
 432             }
 433             if (input != null) {
 434                 input.position(inputPos + read);
 435             } else {
 436                 this.inputPos = inputPos + read;
 437             }
 438             bytesWritten += written;
 439             bytesRead += read;
 440             return written;
 441         }
 442     }
 443 
 444     /**
 445      * Uncompresses bytes into specified buffer. Returns actual number
 446      * of bytes uncompressed. A return value of 0 indicates that
 447      * needsInput() or needsDictionary() should be called in order to
 448      * determine if more input data or a preset dictionary is required.
 449      * In the latter case, getAdler() can be used to get the Adler-32
 450      * value of the dictionary required.
 451      * <p>
 452      * The {@linkplain #getRemaining() remaining byte count} will be reduced by
 453      * the number of consumed input bytes.  If the {@link #setInput(ByteBuffer)}
 454      * method was called to provide a buffer for input, the input buffer's position
 455      * will be advanced the number of consumed bytes.
 456      * <p>
 457      * These byte totals, as well as
 458      * the {@linkplain #getBytesRead() total bytes read}
 459      * and the {@linkplain #getBytesWritten() total bytes written}
 460      * values, will be updated even in the event that a {@link DataFormatException}
 461      * is thrown to reflect the amount of data consumed and produced before the
 462      * exception occurred.
 463      *
 464      * @param output the buffer for the uncompressed data
 465      * @return the actual number of uncompressed bytes
 466      * @throws DataFormatException if the compressed data format is invalid
 467      * @see Inflater#needsInput
 468      * @see Inflater#needsDictionary
 469      */
 470     public int inflate(byte[] output) throws DataFormatException {
 471         return inflate(output, 0, output.length);
 472     }
 473 
 474     /**
 475      * Uncompresses bytes into specified buffer. Returns actual number
 476      * of bytes uncompressed. A return value of 0 indicates that
 477      * needsInput() or needsDictionary() should be called in order to
 478      * determine if more input data or a preset dictionary is required.
 479      * In the latter case, getAdler() can be used to get the Adler-32
 480      * value of the dictionary required.
 481      * <p>
 482      * On success, the position of the given {@code output} byte buffer will be
 483      * advanced by as many bytes as were produced by the operation, which is equal
 484      * to the number returned by this method.  Note that the position of the
 485      * {@code output} buffer will be advanced even in the event that a
 486      * {@link DataFormatException} is thrown.
 487      * <p>
 488      * The {@linkplain #getRemaining() remaining byte count} will be reduced by
 489      * the number of consumed input bytes.  If the {@link #setInput(ByteBuffer)}
 490      * method was called to provide a buffer for input, the input buffer's position
 491      * will be advanced the number of consumed bytes.
 492      * <p>
 493      * These byte totals, as well as
 494      * the {@linkplain #getBytesRead() total bytes read}
 495      * and the {@linkplain #getBytesWritten() total bytes written}
 496      * values, will be updated even in the event that a {@link DataFormatException}
 497      * is thrown to reflect the amount of data consumed and produced before the
 498      * exception occurred.
 499      *
 500      * @param output the buffer for the uncompressed data
 501      * @return the actual number of uncompressed bytes
 502      * @throws DataFormatException if the compressed data format is invalid
 503      * @throws ReadOnlyBufferException if the given output buffer is read-only
 504      * @see Inflater#needsInput
 505      * @see Inflater#needsDictionary
 506      * @since 11
 507      */
 508     public int inflate(ByteBuffer output) throws DataFormatException {
 509         if (output.isReadOnly()) {
 510             throw new ReadOnlyBufferException();
 511         }
 512         synchronized (zsRef) {
 513             ensureOpen();
 514             ByteBuffer input = this.input;
 515             long result;
 516             int inputPos;
 517             int outputPos = output.position();
 518             int outputRem = Math.max(output.limit() - outputPos, 0);
 519             try {
 520                 if (input == null) {
 521                     inputPos = this.inputPos;
 522                     try {
 523                         if (output.isDirect()) {
 524                             long outputAddress = ((DirectBuffer) output).address();
 525                             try {
 526                                 result = inflateBytesBuffer(zsRef.address(),
 527                                     inputArray, inputPos, inputLim - inputPos,
 528                                     outputAddress + outputPos, outputRem);
 529                             } finally {
 530                                 Reference.reachabilityFence(output);
 531                             }
 532                         } else {
 533                             byte[] outputArray = ZipUtils.getBufferArray(output);
 534                             int outputOffset = ZipUtils.getBufferOffset(output);
 535                             result = inflateBytesBytes(zsRef.address(),
 536                                 inputArray, inputPos, inputLim - inputPos,
 537                                 outputArray, outputOffset + outputPos, outputRem);
 538                         }
 539                     } catch (DataFormatException e) {
 540                         this.inputPos = inputPos + inputConsumed;
 541                         throw e;
 542                     }
 543                 } else {
 544                     inputPos = input.position();
 545                     int inputRem = Math.max(input.limit() - inputPos, 0);
 546                     try {
 547                         if (input.isDirect()) {
 548                             long inputAddress = ((DirectBuffer) input).address();
 549                             try {
 550                                 if (output.isDirect()) {
 551                                     long outputAddress = ((DirectBuffer) output).address();
 552                                     try {
 553                                         result = inflateBufferBuffer(zsRef.address(),
 554                                             inputAddress + inputPos, inputRem,
 555                                             outputAddress + outputPos, outputRem);
 556                                     } finally {
 557                                         Reference.reachabilityFence(output);
 558                                     }
 559                                 } else {
 560                                     byte[] outputArray = ZipUtils.getBufferArray(output);
 561                                     int outputOffset = ZipUtils.getBufferOffset(output);
 562                                     result = inflateBufferBytes(zsRef.address(),
 563                                         inputAddress + inputPos, inputRem,
 564                                         outputArray, outputOffset + outputPos, outputRem);
 565                                 }
 566                             } finally {
 567                                 Reference.reachabilityFence(input);
 568                             }
 569                         } else {
 570                             byte[] inputArray = ZipUtils.getBufferArray(input);
 571                             int inputOffset = ZipUtils.getBufferOffset(input);
 572                             if (output.isDirect()) {
 573                                 long outputAddress = ((DirectBuffer) output).address();
 574                                 try {
 575                                     result = inflateBytesBuffer(zsRef.address(),
 576                                         inputArray, inputOffset + inputPos, inputRem,
 577                                         outputAddress + outputPos, outputRem);
 578                                 } finally {
 579                                     Reference.reachabilityFence(output);
 580                                 }
 581                             } else {
 582                                 byte[] outputArray = ZipUtils.getBufferArray(output);
 583                                 int outputOffset = ZipUtils.getBufferOffset(output);
 584                                 result = inflateBytesBytes(zsRef.address(),
 585                                     inputArray, inputOffset + inputPos, inputRem,
 586                                     outputArray, outputOffset + outputPos, outputRem);
 587                             }
 588                         }
 589                     } catch (DataFormatException e) {
 590                         input.position(inputPos + inputConsumed);
 591                         throw e;
 592                     }
 593                 }
 594             } catch (DataFormatException e) {
 595                 bytesRead += inputConsumed;
 596                 inputConsumed = 0;
 597                 int written = outputConsumed;
 598                 output.position(outputPos + written);
 599                 bytesWritten += written;
 600                 outputConsumed = 0;
 601                 throw e;
 602             }
 603             int read = (int) (result & 0x7fff_ffffL);
 604             int written = (int) (result >>> 31 & 0x7fff_ffffL);
 605             if ((result >>> 62 & 1) != 0) {
 606                 finished = true;
 607             }
 608             if ((result >>> 63 & 1) != 0) {
 609                 needDict = true;
 610             }
 611             if (input != null) {
 612                 input.position(inputPos + read);
 613             } else {
 614                 this.inputPos = inputPos + read;
 615             }
 616             // Note: this method call also serves to keep the byteBuffer ref alive
 617             output.position(outputPos + written);
 618             bytesWritten += written;
 619             bytesRead += read;
 620             return written;
 621         }
 622     }
 623 
 624     /**
 625      * Returns the ADLER-32 value of the uncompressed data.
 626      * @return the ADLER-32 value of the uncompressed data
 627      */
 628     public int getAdler() {
 629         synchronized (zsRef) {
 630             ensureOpen();
 631             return getAdler(zsRef.address());
 632         }
 633     }
 634 
 635     /**
 636      * Returns the total number of compressed bytes input so far.
 637      *
 638      * <p>Since the number of bytes may be greater than
 639      * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
 640      * the preferred means of obtaining this information.</p>
 641      *


 674     /**
 675      * Returns the total number of uncompressed bytes output so far.
 676      *
 677      * @return the total (non-negative) number of uncompressed bytes output so far
 678      * @since 1.5
 679      */
 680     public long getBytesWritten() {
 681         synchronized (zsRef) {
 682             ensureOpen();
 683             return bytesWritten;
 684         }
 685     }
 686 
 687     /**
 688      * Resets inflater so that a new set of input data can be processed.
 689      */
 690     public void reset() {
 691         synchronized (zsRef) {
 692             ensureOpen();
 693             reset(zsRef.address());
 694             input = ZipUtils.defaultBuf;
 695             inputArray = null;
 696             finished = false;
 697             needDict = false;

 698             bytesRead = bytesWritten = 0;
 699         }
 700     }
 701 
 702     /**
 703      * Closes the decompressor and discards any unprocessed input.
 704      *
 705      * This method should be called when the decompressor is no longer
 706      * being used. Once this method is called, the behavior of the
 707      * Inflater object is undefined.
 708      */
 709     public void end() {
 710         synchronized (zsRef) {
 711             zsRef.clean();
 712             input = ZipUtils.defaultBuf;
 713             inputArray = null;
 714         }
 715     }
 716 
 717     /**
 718      * Closes the decompressor when garbage is collected.
 719      *
 720      * @implSpec
 721      * If this {@code Inflater} has been subclassed and the {@code end} method
 722      * has been overridden, the {@code end} method will be called when the
 723      * inflater is unreachable.
 724      *
 725      * @deprecated The {@code finalize} method has been deprecated and will be
 726      *     removed. It is implemented as a no-op. Subclasses that override
 727      *     {@code finalize} in order to perform cleanup should be modified to use
 728      *     alternative cleanup mechanisms and remove the overriding {@code finalize}
 729      *     method. The recommended cleanup for compressor is to explicitly call
 730      *     {@code end} method when it is no longer in use. If the {@code end} is
 731      *     not invoked explicitly the resource of the compressor will be released
 732      *     when the instance becomes unreachable,
 733      */
 734     @Deprecated(since="9", forRemoval=true)
 735     protected void finalize() {}
 736 
 737     private void ensureOpen () {
 738         assert Thread.holdsLock(zsRef);
 739         if (zsRef.address() == 0)
 740             throw new NullPointerException("Inflater has been closed");
 741     }
 742 






 743     private static native void initIDs();
 744     private static native long init(boolean nowrap);
 745     private static native void setDictionary(long addr, byte[] b, int off,
 746                                              int len);
 747     private static native void setDictionaryBuffer(long addr, long bufAddress, int len);
 748     private native long inflateBytesBytes(long addr,
 749         byte[] inputArray, int inputOff, int inputLen,
 750         byte[] outputArray, int outputOff, int outputLen) throws DataFormatException;
 751     private native long inflateBytesBuffer(long addr,
 752         byte[] inputArray, int inputOff, int inputLen,
 753         long outputAddress, int outputLen) throws DataFormatException;
 754     private native long inflateBufferBytes(long addr,
 755         long inputAddress, int inputLen,
 756         byte[] outputArray, int outputOff, int outputLen) throws DataFormatException;
 757     private native long inflateBufferBuffer(long addr,
 758         long inputAddress, int inputLen,
 759         long outputAddress, int outputLen) throws DataFormatException;
 760     private static native int getAdler(long addr);
 761     private static native void reset(long addr);
 762     private static native void end(long addr);
 763 
 764     /**
 765      * A reference to the native zlib's z_stream structure. It also
 766      * serves as the "cleaner" to clean up the native resource when
 767      * the Inflater is ended, closed or cleaned.
 768      */
 769     static class InflaterZStreamRef implements Runnable {
 770 
 771         private long address;
 772         private final Cleanable cleanable;
 773 
 774         private InflaterZStreamRef(Inflater owner, long addr) {
 775             this.cleanable = (owner != null) ? CleanerFactory.cleaner().register(owner, this) : null;
 776             this.address = addr;
 777         }
 778 
 779         long address() {