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 compression 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 deflates sequences of bytes into ZLIB compressed data format.
  46  * The input byte sequence is provided in either byte array or byte buffer,
  47  * via one of the {@code setInput()} methods. The output byte sequence is
  48  * written to the output byte array or byte buffer passed to the
  49  * {@code deflate()} methods.
  50  * <p>
  51  * The following code fragment demonstrates a trivial compression
  52  * and decompression of a string using {@code Deflater} and
  53  * {@code Inflater}.
  54  *
  55  * <blockquote><pre>
  56  * try {
  57  *     // Encode a String into bytes
  58  *     String inputString = "blahblahblah";
  59  *     byte[] input = inputString.getBytes("UTF-8");
  60  *
  61  *     // Compress the bytes
  62  *     byte[] output = new byte[100];
  63  *     Deflater compresser = new Deflater();
  64  *     compresser.setInput(input);
  65  *     compresser.finish();
  66  *     int compressedDataLength = compresser.deflate(output);
  67  *     compresser.end();
  68  *
  69  *     // Decompress the bytes
  70  *     Inflater decompresser = new Inflater();
  71  *     decompresser.setInput(output, 0, compressedDataLength);
  72  *     byte[] result = new byte[100];
  73  *     int resultLength = decompresser.inflate(result);
  74  *     decompresser.end();
  75  *
  76  *     // Decode the bytes into a String
  77  *     String outputString = new String(result, 0, resultLength, "UTF-8");
  78  * } catch(java.io.UnsupportedEncodingException ex) {
  79  *     // handle
  80  * } catch (java.util.zip.DataFormatException ex) {
  81  *     // handle
  82  * }
  83  * </pre></blockquote>
  84  *
  85  * @apiNote
  86  * To release resources used by this {@code Deflater}, the {@link #end()} method
  87  * should be called explicitly. Subclasses are responsible for the cleanup of resources
  88  * acquired by the subclass. Subclasses that override {@link #finalize()} in order
  89  * to perform cleanup should be modified to use alternative cleanup mechanisms such
  90  * as {@link java.lang.ref.Cleaner} and remove the overriding {@code finalize} method.
  91  *
  92  * @implSpec
  93  * If this {@code Deflater} has been subclassed and the {@code end} method has been
  94  * overridden, the {@code end} method will be called by the finalization when the
  95  * deflater is unreachable. But the subclasses should not depend on this specific
  96  * implementation; the finalization is not reliable and the {@code finalize} method
  97  * is deprecated to be removed.
  98  *
  99  * @see         Inflater
 100  * @author      David Connelly
 101  * @since 1.1
 102  */
 103 
 104 public class Deflater {
 105 
 106     private final DeflaterZStreamRef zsRef;
 107     private ByteBuffer input = ZipUtils.defaultBuf;
 108     private byte[] inputArray;
 109     private int inputPos, inputLim;
 110     private int level, strategy;
 111     private boolean setParams;
 112     private boolean finish, finished;
 113     private long bytesRead;
 114     private long bytesWritten;
 115 
 116     /**
 117      * Compression method for the deflate algorithm (the only one currently
 118      * supported).
 119      */
 120     public static final int DEFLATED = 8;
 121 
 122     /**
 123      * Compression level for no compression.
 124      */
 125     public static final int NO_COMPRESSION = 0;
 126 
 127     /**
 128      * Compression level for fastest compression.
 129      */
 130     public static final int BEST_SPEED = 1;
 131 
 132     /**
 133      * Compression level for best compression.
 134      */
 135     public static final int BEST_COMPRESSION = 9;
 136 
 137     /**
 138      * Default compression level.
 139      */
 140     public static final int DEFAULT_COMPRESSION = -1;
 141 
 142     /**
 143      * Compression strategy best used for data consisting mostly of small
 144      * values with a somewhat random distribution. Forces more Huffman coding
 145      * and less string matching.
 146      */
 147     public static final int FILTERED = 1;
 148 
 149     /**
 150      * Compression strategy for Huffman coding only.
 151      */
 152     public static final int HUFFMAN_ONLY = 2;
 153 
 154     /**
 155      * Default compression strategy.
 156      */
 157     public static final int DEFAULT_STRATEGY = 0;
 158 
 159     /**
 160      * Compression flush mode used to achieve best compression result.
 161      *
 162      * @see Deflater#deflate(byte[], int, int, int)
 163      * @since 1.7
 164      */
 165     public static final int NO_FLUSH = 0;
 166 
 167     /**
 168      * Compression flush mode used to flush out all pending output; may
 169      * degrade compression for some compression algorithms.
 170      *
 171      * @see Deflater#deflate(byte[], int, int, int)
 172      * @since 1.7
 173      */
 174     public static final int SYNC_FLUSH = 2;
 175 
 176     /**
 177      * Compression flush mode used to flush out all pending output and
 178      * reset the deflater. Using this mode too often can seriously degrade
 179      * compression.
 180      *
 181      * @see Deflater#deflate(byte[], int, int, int)
 182      * @since 1.7
 183      */
 184     public static final int FULL_FLUSH = 3;
 185 
 186     /**
 187      * Flush mode to use at the end of output.  Can only be provided by the
 188      * user by way of {@link #finish()}.
 189      */
 190     private static final int FINISH = 4;
 191 
 192     static {
 193         ZipUtils.loadLibrary();
 194     }
 195 
 196     /**
 197      * Creates a new compressor using the specified compression level.
 198      * If 'nowrap' is true then the ZLIB header and checksum fields will
 199      * not be used in order to support the compression format used in
 200      * both GZIP and PKZIP.
 201      * @param level the compression level (0-9)
 202      * @param nowrap if true then use GZIP compatible compression
 203      */
 204     public Deflater(int level, boolean nowrap) {
 205         this.level = level;
 206         this.strategy = DEFAULT_STRATEGY;
 207         this.zsRef = DeflaterZStreamRef.get(this,
 208                                     init(level, DEFAULT_STRATEGY, nowrap));
 209     }
 210 
 211     /**
 212      * Creates a new compressor using the specified compression level.
 213      * Compressed data will be generated in ZLIB format.
 214      * @param level the compression level (0-9)
 215      */
 216     public Deflater(int level) {
 217         this(level, false);
 218     }
 219 
 220     /**
 221      * Creates a new compressor with the default compression level.
 222      * Compressed data will be generated in ZLIB format.
 223      */
 224     public Deflater() {
 225         this(DEFAULT_COMPRESSION, false);
 226     }
 227 
 228     /**
 229      * Sets input data for compression.
 230      * <p>
 231      * One of the {@code setInput()} methods should be called whenever
 232      * {@code needsInput()} returns true indicating that more input data
 233      * is required.
 234      * <p>
 235      * @param input the input data bytes
 236      * @param off the start offset of the data
 237      * @param len the length of the data
 238      * @see Deflater#needsInput
 239      */
 240     public void setInput(byte[] input, int off, int len) {
 241         if (off < 0 || len < 0 || off > input.length - len) {
 242             throw new ArrayIndexOutOfBoundsException();
 243         }
 244         synchronized (zsRef) {
 245             this.input = null;
 246             this.inputArray = input;
 247             this.inputPos = off;
 248             this.inputLim = off + len;
 249         }
 250     }
 251 
 252     /**
 253      * Sets input data for compression.
 254      * <p>
 255      * One of the {@code setInput()} methods should be called whenever
 256      * {@code needsInput()} returns true indicating that more input data
 257      * is required.
 258      * <p>
 259      * @param input the input data bytes
 260      * @see Deflater#needsInput
 261      */
 262     public void setInput(byte[] input) {
 263         setInput(input, 0, input.length);
 264     }
 265 
 266     /**
 267      * Sets input data for compression.
 268      * <p>
 269      * One of the {@code setInput()} methods should be called whenever
 270      * {@code needsInput()} returns true indicating that more input data
 271      * is required.
 272      * <p>
 273      * The given buffer's position will be advanced as deflate
 274      * operations are performed, up to the buffer's limit.
 275      * The input buffer may be modified (refilled) between deflate
 276      * operations; doing so is equivalent to creating a new buffer
 277      * and setting it with this method.
 278      * <p>
 279      * Modifying the input buffer's contents, position, or limit
 280      * concurrently with an deflate operation will result in
 281      * undefined behavior, which may include incorrect operation
 282      * results or operation failure.
 283      *
 284      * @param input the input data bytes
 285      * @see Deflater#needsInput
 286      * @since 11
 287      */
 288     public void setInput(ByteBuffer input) {
 289         Objects.requireNonNull(input);
 290         synchronized (zsRef) {
 291             this.input = input;
 292             this.inputArray = null;
 293         }
 294     }
 295 
 296     /**
 297      * Sets preset dictionary for compression. A preset dictionary is used
 298      * when the history buffer can be predetermined. When the data is later
 299      * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
 300      * in order to get the Adler-32 value of the dictionary required for
 301      * decompression.
 302      * @param dictionary the dictionary data bytes
 303      * @param off the start offset of the data
 304      * @param len the length of the data
 305      * @see Inflater#inflate
 306      * @see Inflater#getAdler
 307      */
 308     public void setDictionary(byte[] dictionary, int off, int len) {
 309         if (off < 0 || len < 0 || off > dictionary.length - len) {
 310             throw new ArrayIndexOutOfBoundsException();
 311         }
 312         synchronized (zsRef) {
 313             ensureOpen();
 314             setDictionary(zsRef.address(), dictionary, off, len);
 315         }
 316     }
 317 
 318     /**
 319      * Sets preset dictionary for compression. A preset dictionary is used
 320      * when the history buffer can be predetermined. When the data is later
 321      * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
 322      * in order to get the Adler-32 value of the dictionary required for
 323      * decompression.
 324      * @param dictionary the dictionary data bytes
 325      * @see Inflater#inflate
 326      * @see Inflater#getAdler
 327      */
 328     public void setDictionary(byte[] dictionary) {
 329         setDictionary(dictionary, 0, dictionary.length);
 330     }
 331 
 332     /**
 333      * Sets preset dictionary for compression. A preset dictionary is used
 334      * when the history buffer can be predetermined. When the data is later
 335      * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
 336      * in order to get the Adler-32 value of the dictionary required for
 337      * decompression.
 338      * <p>
 339      * The bytes in given byte buffer will be fully consumed by this method.  On
 340      * return, its position will equal its limit.
 341      *
 342      * @param dictionary the dictionary data bytes
 343      * @see Inflater#inflate
 344      * @see Inflater#getAdler
 345      */
 346     public void setDictionary(ByteBuffer dictionary) {
 347         synchronized (zsRef) {
 348             int position = dictionary.position();
 349             int remaining = Math.max(dictionary.limit() - position, 0);
 350             ensureOpen();
 351             if (dictionary.isDirect()) {
 352                 long address = ((DirectBuffer) dictionary).address();
 353                 try {
 354                     setDictionaryBuffer(zsRef.address(), address + position, remaining);
 355                 } finally {
 356                     Reference.reachabilityFence(dictionary);
 357                 }
 358             } else {
 359                 byte[] array = ZipUtils.getBufferArray(dictionary);
 360                 int offset = ZipUtils.getBufferOffset(dictionary);
 361                 setDictionary(zsRef.address(), array, offset + position, remaining);
 362             }
 363             dictionary.position(position + remaining);
 364         }
 365     }
 366 
 367     /**
 368      * Sets the compression strategy to the specified value.
 369      *
 370      * <p> If the compression strategy is changed, the next invocation
 371      * of {@code deflate} will compress the input available so far with
 372      * the old strategy (and may be flushed); the new strategy will take
 373      * effect only after that invocation.
 374      *
 375      * @param strategy the new compression strategy
 376      * @exception IllegalArgumentException if the compression strategy is
 377      *                                     invalid
 378      */
 379     public void setStrategy(int strategy) {
 380         switch (strategy) {
 381           case DEFAULT_STRATEGY:
 382           case FILTERED:
 383           case HUFFMAN_ONLY:
 384             break;
 385           default:
 386             throw new IllegalArgumentException();
 387         }
 388         synchronized (zsRef) {
 389             if (this.strategy != strategy) {
 390                 this.strategy = strategy;
 391                 setParams = true;
 392             }
 393         }
 394     }
 395 
 396     /**
 397      * Sets the compression level to the specified value.
 398      *
 399      * <p> If the compression level is changed, the next invocation
 400      * of {@code deflate} will compress the input available so far
 401      * with the old level (and may be flushed); the new level will
 402      * take effect only after that invocation.
 403      *
 404      * @param level the new compression level (0-9)
 405      * @exception IllegalArgumentException if the compression level is invalid
 406      */
 407     public void setLevel(int level) {
 408         if ((level < 0 || level > 9) && level != DEFAULT_COMPRESSION) {
 409             throw new IllegalArgumentException("invalid compression level");
 410         }
 411         synchronized (zsRef) {
 412             if (this.level != level) {
 413                 this.level = level;
 414                 setParams = true;
 415             }
 416         }
 417     }
 418 
 419     /**
 420      * Returns true if no data remains in the input buffer. This can
 421      * be used to determine if one of the {@code setInput()} methods should be
 422      * called in order to provide more input.
 423      *
 424      * @return true if the input data buffer is empty and setInput()
 425      * should be called in order to provide more input
 426      */
 427     public boolean needsInput() {
 428         synchronized (zsRef) {
 429             ByteBuffer input = this.input;
 430             return input == null ? inputLim == inputPos : ! input.hasRemaining();
 431         }
 432     }
 433 
 434     /**
 435      * When called, indicates that compression should end with the current
 436      * contents of the input buffer.
 437      */
 438     public void finish() {
 439         synchronized (zsRef) {
 440             finish = true;
 441         }
 442     }
 443 
 444     /**
 445      * Returns true if the end of the compressed data output stream has
 446      * been reached.
 447      * @return true if the end of the compressed data output stream has
 448      * been reached
 449      */
 450     public boolean finished() {
 451         synchronized (zsRef) {
 452             return finished;
 453         }
 454     }
 455 
 456     /**
 457      * Compresses the input data and fills specified buffer with compressed
 458      * data. Returns actual number of bytes of compressed data. A return value
 459      * of 0 indicates that {@link #needsInput() needsInput} should be called
 460      * in order to determine if more input data is required.
 461      *
 462      * <p>This method uses {@link #NO_FLUSH} as its compression flush mode.
 463      * An invocation of this method of the form {@code deflater.deflate(b, off, len)}
 464      * yields the same result as the invocation of
 465      * {@code deflater.deflate(b, off, len, Deflater.NO_FLUSH)}.
 466      *
 467      * @param output the buffer for the compressed data
 468      * @param off the start offset of the data
 469      * @param len the maximum number of bytes of compressed data
 470      * @return the actual number of bytes of compressed data written to the
 471      *         output buffer
 472      */
 473     public int deflate(byte[] output, int off, int len) {
 474         return deflate(output, off, len, NO_FLUSH);
 475     }
 476 
 477     /**
 478      * Compresses the input data and fills specified buffer with compressed
 479      * data. Returns actual number of bytes of compressed data. A return value
 480      * of 0 indicates that {@link #needsInput() needsInput} should be called
 481      * in order to determine if more input data is required.
 482      *
 483      * <p>This method uses {@link #NO_FLUSH} as its compression flush mode.
 484      * An invocation of this method of the form {@code deflater.deflate(b)}
 485      * yields the same result as the invocation of
 486      * {@code deflater.deflate(b, 0, b.length, Deflater.NO_FLUSH)}.
 487      *
 488      * @param output the buffer for the compressed data
 489      * @return the actual number of bytes of compressed data written to the
 490      *         output buffer
 491      */
 492     public int deflate(byte[] output) {
 493         return deflate(output, 0, output.length, NO_FLUSH);
 494     }
 495 
 496     /**
 497      * Compresses the input data and fills specified buffer with compressed
 498      * data. Returns actual number of bytes of compressed data. A return value
 499      * of 0 indicates that {@link #needsInput() needsInput} should be called
 500      * in order to determine if more input data is required.
 501      *
 502      * <p>This method uses {@link #NO_FLUSH} as its compression flush mode.
 503      * An invocation of this method of the form {@code deflater.deflate(output)}
 504      * yields the same result as the invocation of
 505      * {@code deflater.deflate(output, Deflater.NO_FLUSH)}.
 506      *
 507      * @param output the buffer for the compressed data
 508      * @return the actual number of bytes of compressed data written to the
 509      *         output buffer
 510      * @since 11
 511      */
 512     public int deflate(ByteBuffer output) {
 513         return deflate(output, NO_FLUSH);
 514     }
 515 
 516     /**
 517      * Compresses the input data and fills the specified buffer with compressed
 518      * data. Returns actual number of bytes of data compressed.
 519      *
 520      * <p>Compression flush mode is one of the following three modes:
 521      *
 522      * <ul>
 523      * <li>{@link #NO_FLUSH}: allows the deflater to decide how much data
 524      * to accumulate, before producing output, in order to achieve the best
 525      * compression (should be used in normal use scenario). A return value
 526      * of 0 in this flush mode indicates that {@link #needsInput()} should
 527      * be called in order to determine if more input data is required.
 528      *
 529      * <li>{@link #SYNC_FLUSH}: all pending output in the deflater is flushed,
 530      * to the specified output buffer, so that an inflater that works on
 531      * compressed data can get all input data available so far (In particular
 532      * the {@link #needsInput()} returns {@code true} after this invocation
 533      * if enough output space is provided). Flushing with {@link #SYNC_FLUSH}
 534      * may degrade compression for some compression algorithms and so it
 535      * should be used only when necessary.
 536      *
 537      * <li>{@link #FULL_FLUSH}: all pending output is flushed out as with
 538      * {@link #SYNC_FLUSH}. The compression state is reset so that the inflater
 539      * that works on the compressed output data can restart from this point
 540      * if previous compressed data has been damaged or if random access is
 541      * desired. Using {@link #FULL_FLUSH} too often can seriously degrade
 542      * compression.
 543      * </ul>
 544      *
 545      * <p>In the case of {@link #FULL_FLUSH} or {@link #SYNC_FLUSH}, if
 546      * the return value is {@code len}, the space available in output
 547      * buffer {@code b}, this method should be invoked again with the same
 548      * {@code flush} parameter and more output space. Make sure that
 549      * {@code len} is greater than 6 to avoid flush marker (5 bytes) being
 550      * repeatedly output to the output buffer every time this method is
 551      * invoked.
 552      *
 553      * <p>If the {@link #setInput(ByteBuffer)} method was called to provide a buffer
 554      * for input, the input buffer's position will be advanced by the number of bytes
 555      * consumed by this operation.
 556      *
 557      * @param output the buffer for the compressed data
 558      * @param off the start offset of the data
 559      * @param len the maximum number of bytes of compressed data
 560      * @param flush the compression flush mode
 561      * @return the actual number of bytes of compressed data written to
 562      *         the output buffer
 563      *
 564      * @throws IllegalArgumentException if the flush mode is invalid
 565      * @since 1.7
 566      */
 567     public int deflate(byte[] output, int off, int len, int flush) {
 568         if (off < 0 || len < 0 || off > output.length - len) {
 569             throw new ArrayIndexOutOfBoundsException();
 570         }
 571         if (flush != NO_FLUSH && flush != SYNC_FLUSH && flush != FULL_FLUSH) {
 572             throw new IllegalArgumentException();
 573         }
 574         synchronized (zsRef) {
 575             ensureOpen();
 576 
 577             ByteBuffer input = this.input;
 578             if (finish) {
 579                 // disregard given flush mode in this case
 580                 flush = FINISH;
 581             }
 582             int params;
 583             if (setParams) {
 584                 // bit 0: true to set params
 585                 // bit 1-2: strategy (0, 1, or 2)
 586                 // bit 3-31: level (0..9 or -1)
 587                 params = 1 | strategy << 1 | level << 3;
 588             } else {
 589                 params = 0;
 590             }
 591             int inputPos;
 592             long result;
 593             if (input == null) {
 594                 inputPos = this.inputPos;
 595                 result = deflateBytesBytes(zsRef.address(),
 596                     inputArray, inputPos, inputLim - inputPos,
 597                     output, off, len,
 598                     flush, params);
 599             } else {
 600                 inputPos = input.position();
 601                 int inputRem = Math.max(input.limit() - inputPos, 0);
 602                 if (input.isDirect()) {
 603                     try {
 604                         long inputAddress = ((DirectBuffer) input).address();
 605                         result = deflateBufferBytes(zsRef.address(),
 606                             inputAddress + inputPos, inputRem,
 607                             output, off, len,
 608                             flush, params);
 609                     } finally {
 610                         Reference.reachabilityFence(input);
 611                     }
 612                 } else {
 613                     byte[] inputArray = ZipUtils.getBufferArray(input);
 614                     int inputOffset = ZipUtils.getBufferOffset(input);
 615                     result = deflateBytesBytes(zsRef.address(),
 616                         inputArray, inputOffset + inputPos, inputRem,
 617                         output, off, len,
 618                         flush, params);
 619                 }
 620             }
 621             int read = (int) (result & 0x7fff_ffffL);
 622             int written = (int) (result >>> 31 & 0x7fff_ffffL);
 623             if ((result >>> 62 & 1) != 0) {
 624                 finished = true;
 625             }
 626             if (params != 0 && (result >>> 63 & 1) == 0) {
 627                 setParams = false;
 628             }
 629             if (input != null) {
 630                 input.position(inputPos + read);
 631             } else {
 632                 this.inputPos = inputPos + read;
 633             }
 634             bytesWritten += written;
 635             bytesRead += read;
 636             return written;
 637         }
 638     }
 639 
 640     /**
 641      * Compresses the input data and fills the specified buffer with compressed
 642      * data. Returns actual number of bytes of data compressed.
 643      *
 644      * <p>Compression flush mode is one of the following three modes:
 645      *
 646      * <ul>
 647      * <li>{@link #NO_FLUSH}: allows the deflater to decide how much data
 648      * to accumulate, before producing output, in order to achieve the best
 649      * compression (should be used in normal use scenario). A return value
 650      * of 0 in this flush mode indicates that {@link #needsInput()} should
 651      * be called in order to determine if more input data is required.
 652      *
 653      * <li>{@link #SYNC_FLUSH}: all pending output in the deflater is flushed,
 654      * to the specified output buffer, so that an inflater that works on
 655      * compressed data can get all input data available so far (In particular
 656      * the {@link #needsInput()} returns {@code true} after this invocation
 657      * if enough output space is provided). Flushing with {@link #SYNC_FLUSH}
 658      * may degrade compression for some compression algorithms and so it
 659      * should be used only when necessary.
 660      *
 661      * <li>{@link #FULL_FLUSH}: all pending output is flushed out as with
 662      * {@link #SYNC_FLUSH}. The compression state is reset so that the inflater
 663      * that works on the compressed output data can restart from this point
 664      * if previous compressed data has been damaged or if random access is
 665      * desired. Using {@link #FULL_FLUSH} too often can seriously degrade
 666      * compression.
 667      * </ul>
 668      *
 669      * <p>In the case of {@link #FULL_FLUSH} or {@link #SYNC_FLUSH}, if
 670      * the return value is equal to the {@linkplain ByteBuffer#remaining() remaining space}
 671      * of the buffer, this method should be invoked again with the same
 672      * {@code flush} parameter and more output space. Make sure that
 673      * the buffer has at least 6 bytes of remaining space to avoid the
 674      * flush marker (5 bytes) being repeatedly output to the output buffer
 675      * every time this method is invoked.
 676      *
 677      * <p>On success, the position of the given {@code output} byte buffer will be
 678      * advanced by as many bytes as were produced by the operation, which is equal
 679      * to the number returned by this method.
 680      *
 681      * <p>If the {@link #setInput(ByteBuffer)} method was called to provide a buffer
 682      * for input, the input buffer's position will be advanced by the number of bytes
 683      * consumed by this operation.
 684      *
 685      * @param output the buffer for the compressed data
 686      * @param flush the compression flush mode
 687      * @return the actual number of bytes of compressed data written to
 688      *         the output buffer
 689      *
 690      * @throws IllegalArgumentException if the flush mode is invalid
 691      * @since 11
 692      */
 693     public int deflate(ByteBuffer output, int flush) {
 694         if (output.isReadOnly()) {
 695             throw new ReadOnlyBufferException();
 696         }
 697         if (flush != NO_FLUSH && flush != SYNC_FLUSH && flush != FULL_FLUSH) {
 698             throw new IllegalArgumentException();
 699         }
 700         synchronized (zsRef) {
 701             ensureOpen();
 702 
 703             ByteBuffer input = this.input;
 704             if (finish) {
 705                 // disregard given flush mode in this case
 706                 flush = FINISH;
 707             }
 708             int params;
 709             if (setParams) {
 710                 // bit 0: true to set params
 711                 // bit 1-2: strategy (0, 1, or 2)
 712                 // bit 3-31: level (0..9 or -1)
 713                 params = 1 | strategy << 1 | level << 3;
 714             } else {
 715                 params = 0;
 716             }
 717             int outputPos = output.position();
 718             int outputRem = Math.max(output.limit() - outputPos, 0);
 719             int inputPos;
 720             long result;
 721             if (input == null) {
 722                 inputPos = this.inputPos;
 723                 if (output.isDirect()) {
 724                     long outputAddress = ((DirectBuffer) output).address();
 725                     try {
 726                         result = deflateBytesBuffer(zsRef.address(),
 727                             inputArray, inputPos, inputLim - inputPos,
 728                             outputAddress + outputPos, outputRem,
 729                             flush, params);
 730                     } finally {
 731                         Reference.reachabilityFence(output);
 732                     }
 733                 } else {
 734                     byte[] outputArray = ZipUtils.getBufferArray(output);
 735                     int outputOffset = ZipUtils.getBufferOffset(output);
 736                     result = deflateBytesBytes(zsRef.address(),
 737                         inputArray, inputPos, inputLim - inputPos,
 738                         outputArray, outputOffset + outputPos, outputRem,
 739                         flush, params);
 740                 }
 741             } else {
 742                 inputPos = input.position();
 743                 int inputRem = Math.max(input.limit() - inputPos, 0);
 744                 if (input.isDirect()) {
 745                     long inputAddress = ((DirectBuffer) input).address();
 746                     try {
 747                         if (output.isDirect()) {
 748                             long outputAddress = outputPos + ((DirectBuffer) output).address();
 749                             try {
 750                                 result = deflateBufferBuffer(zsRef.address(),
 751                                     inputAddress + inputPos, inputRem,
 752                                     outputAddress, outputRem,
 753                                     flush, params);
 754                             } finally {
 755                                 Reference.reachabilityFence(output);
 756                             }
 757                         } else {
 758                             byte[] outputArray = ZipUtils.getBufferArray(output);
 759                             int outputOffset = ZipUtils.getBufferOffset(output);
 760                             result = deflateBufferBytes(zsRef.address(),
 761                                 inputAddress + inputPos, inputRem,
 762                                 outputArray, outputOffset + outputPos, outputRem,
 763                                 flush, params);
 764                         }
 765                     } finally {
 766                         Reference.reachabilityFence(input);
 767                     }
 768                 } else {
 769                     byte[] inputArray = ZipUtils.getBufferArray(input);
 770                     int inputOffset = ZipUtils.getBufferOffset(input);
 771                     if (output.isDirect()) {
 772                         long outputAddress = ((DirectBuffer) output).address();
 773                         try {
 774                             result = deflateBytesBuffer(zsRef.address(),
 775                                 inputArray, inputOffset + inputPos, inputRem,
 776                                 outputAddress + outputPos, outputRem,
 777                                 flush, params);
 778                         } finally {
 779                             Reference.reachabilityFence(output);
 780                         }
 781                     } else {
 782                         byte[] outputArray = ZipUtils.getBufferArray(output);
 783                         int outputOffset = ZipUtils.getBufferOffset(output);
 784                         result = deflateBytesBytes(zsRef.address(),
 785                             inputArray, inputOffset + inputPos, inputRem,
 786                             outputArray, outputOffset + outputPos, outputRem,
 787                             flush, params);
 788                     }
 789                 }
 790             }
 791             int read = (int) (result & 0x7fff_ffffL);
 792             int written = (int) (result >>> 31 & 0x7fff_ffffL);
 793             if ((result >>> 62 & 1) != 0) {
 794                 finished = true;
 795             }
 796             if (params != 0 && (result >>> 63 & 1) == 0) {
 797                 setParams = false;
 798             }
 799             if (input != null) {
 800                 input.position(inputPos + read);
 801             } else {
 802                 this.inputPos = inputPos + read;
 803             }
 804             output.position(outputPos + written);
 805             bytesWritten += written;
 806             bytesRead += read;
 807             return written;
 808         }
 809     }
 810 
 811     /**
 812      * Returns the ADLER-32 value of the uncompressed data.
 813      * @return the ADLER-32 value of the uncompressed data
 814      */
 815     public int getAdler() {
 816         synchronized (zsRef) {
 817             ensureOpen();
 818             return getAdler(zsRef.address());
 819         }
 820     }
 821 
 822     /**
 823      * Returns the total number of uncompressed bytes input so far.
 824      *
 825      * <p>Since the number of bytes may be greater than
 826      * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
 827      * the preferred means of obtaining this information.</p>
 828      *
 829      * @return the total number of uncompressed bytes input so far
 830      */
 831     public int getTotalIn() {
 832         return (int) getBytesRead();
 833     }
 834 
 835     /**
 836      * Returns the total number of uncompressed bytes input so far.
 837      *
 838      * @return the total (non-negative) number of uncompressed bytes input so far
 839      * @since 1.5
 840      */
 841     public long getBytesRead() {
 842         synchronized (zsRef) {
 843             ensureOpen();
 844             return bytesRead;
 845         }
 846     }
 847 
 848     /**
 849      * Returns the total number of compressed bytes output so far.
 850      *
 851      * <p>Since the number of bytes may be greater than
 852      * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
 853      * the preferred means of obtaining this information.</p>
 854      *
 855      * @return the total number of compressed bytes output so far
 856      */
 857     public int getTotalOut() {
 858         return (int) getBytesWritten();
 859     }
 860 
 861     /**
 862      * Returns the total number of compressed bytes output so far.
 863      *
 864      * @return the total (non-negative) number of compressed bytes output so far
 865      * @since 1.5
 866      */
 867     public long getBytesWritten() {
 868         synchronized (zsRef) {
 869             ensureOpen();
 870             return bytesWritten;
 871         }
 872     }
 873 
 874     /**
 875      * Resets deflater so that a new set of input data can be processed.
 876      * Keeps current compression level and strategy settings.
 877      */
 878     public void reset() {
 879         synchronized (zsRef) {
 880             ensureOpen();
 881             reset(zsRef.address());
 882             finish = false;
 883             finished = false;
 884             input = ZipUtils.defaultBuf;
 885             inputArray = null;
 886             bytesRead = bytesWritten = 0;
 887         }
 888     }
 889 
 890     /**
 891      * Closes the compressor and discards any unprocessed input.
 892      *
 893      * This method should be called when the compressor is no longer
 894      * being used. Once this method is called, the behavior of the
 895      * Deflater object is undefined.
 896      */
 897     public void end() {
 898         synchronized (zsRef) {
 899             zsRef.clean();
 900             input = ZipUtils.defaultBuf;
 901         }
 902     }
 903 
 904     /**
 905      * Closes the compressor when garbage is collected.
 906      *
 907      * @deprecated The {@code finalize} method has been deprecated and will be
 908      *     removed. It is implemented as a no-op. Subclasses that override
 909      *     {@code finalize} in order to perform cleanup should be modified to use
 910      *     alternative cleanup mechanisms and to remove the overriding {@code finalize}
 911      *     method. The recommended cleanup for compressor is to explicitly call
 912      *     {@code end} method when it is no longer in use. If the {@code end} is
 913      *     not invoked explicitly the resource of the compressor will be released
 914      *     when the instance becomes unreachable.
 915      */
 916     @Deprecated(since="9", forRemoval=true)
 917     protected void finalize() {}
 918 
 919     private void ensureOpen() {
 920         assert Thread.holdsLock(zsRef);
 921         if (zsRef.address() == 0)
 922             throw new NullPointerException("Deflater has been closed");
 923     }
 924 
 925     private static native long init(int level, int strategy, boolean nowrap);
 926     private static native void setDictionary(long addr, byte[] b, int off,
 927                                              int len);
 928     private static native void setDictionaryBuffer(long addr, long bufAddress, int len);
 929     private native long deflateBytesBytes(long addr,
 930         byte[] inputArray, int inputOff, int inputLen,
 931         byte[] outputArray, int outputOff, int outputLen,
 932         int flush, int params);
 933     private native long deflateBytesBuffer(long addr,
 934         byte[] inputArray, int inputOff, int inputLen,
 935         long outputAddress, int outputLen,
 936         int flush, int params);
 937     private native long deflateBufferBytes(long addr,
 938         long inputAddress, int inputLen,
 939         byte[] outputArray, int outputOff, int outputLen,
 940         int flush, int params);
 941     private native long deflateBufferBuffer(long addr,
 942         long inputAddress, int inputLen,
 943         long outputAddress, int outputLen,
 944         int flush, int params);
 945     private static native int getAdler(long addr);
 946     private static native void reset(long addr);
 947     private static native void end(long addr);
 948 
 949     /**
 950      * A reference to the native zlib's z_stream structure. It also
 951      * serves as the "cleaner" to clean up the native resource when
 952      * the Deflater is ended, closed or cleaned.
 953      */
 954     static class DeflaterZStreamRef implements Runnable {
 955 
 956         private long address;
 957         private final Cleanable cleanable;
 958 
 959         private DeflaterZStreamRef(Deflater owner, long addr) {
 960             this.cleanable = (owner != null) ? CleanerFactory.cleaner().register(owner, this) : null;
 961             this.address = addr;
 962         }
 963 
 964         long address() {
 965             return address;
 966         }
 967 
 968         void clean() {
 969             cleanable.clean();
 970         }
 971 
 972         public synchronized void run() {
 973             long addr = address;
 974             address = 0;
 975             if (addr != 0) {
 976                 end(addr);
 977             }
 978         }
 979 
 980         /*
 981          * If {@code Deflater} has been subclassed and the {@code end} method is
 982          * overridden, uses {@code finalizer} mechanism for resource cleanup. So
 983          * {@code end} method can be called when the {@code Deflater} is unreachable.
 984          * This mechanism will be removed when the {@code finalize} method is
 985          * removed from {@code Deflater}.
 986          */
 987         static DeflaterZStreamRef get(Deflater owner, long addr) {
 988             Class<?> clz = owner.getClass();
 989             while (clz != Deflater.class) {
 990                 try {
 991                     clz.getDeclaredMethod("end");
 992                     return new FinalizableZStreamRef(owner, addr);
 993                 } catch (NoSuchMethodException nsme) {}
 994                 clz = clz.getSuperclass();
 995             }
 996             return new DeflaterZStreamRef(owner, addr);
 997         }
 998 
 999         private static class FinalizableZStreamRef extends DeflaterZStreamRef {
1000             final Deflater owner;
1001 
1002             FinalizableZStreamRef (Deflater owner, long addr) {
1003                 super(null, addr);
1004                 this.owner = owner;
1005             }
1006 
1007             @Override
1008             void clean() {
1009                 run();
1010             }
1011 
1012             @Override
1013             @SuppressWarnings("deprecation")
1014             protected void finalize() {
1015                 owner.end();
1016             }
1017         }
1018     }
1019 }