JDK-8020687 : Deflater.setLevel does not work as expected
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util.jar
  • Affected Version: 6,7
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_7
  • Submitted: 2013-07-13
  • Updated: 2013-11-21
  • Resolved: 2013-09-15
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8 b108Fixed
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version  " 1.7.0_25 " 
Java(TM) SE Runtime Environment (build 1.7.0_25-b17)
Java HotSpot(TM) Client VM (build 23.25-b01, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Windows Version 6.1.7601


A DESCRIPTION OF THE PROBLEM :
Deflater.setLevel() does not seem to set the compression level. Worse than a mere NOOP, if one calls deflater.setLevel() with an argument different that the already set by the constructor (explicitly or implicitly), the deflate stops working as expected.

Tested also with 1.6.0_07-b06 in Linux.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the program below

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
level in constructor: len=8 [120, -38, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
level via setLevel(): len=8 [120, -38, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]

ACTUAL -
level in constructor: len=8 [120, -38, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
level via setLevel(): len=0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.Arrays;
import java.util.zip.Deflater;

public class TestDeflater {

public static void test1 () throws Exception {
         byte[] output = new byte[16];
         Deflater compresser = new Deflater(Deflater.BEST_COMPRESSION);
         compresser.finish();
         int len = compresser.deflate(output);
         System.out.println( " level in constructor: len= " + len+  "   "  +Arrays.toString(output));
    }
    public static void test2 () throws Exception {
         byte[] output = new byte[16];
         Deflater compresser = new Deflater();
         compresser.setLevel(Deflater.BEST_COMPRESSION);
         compresser.setInput( " blah " .getBytes( " UTF-8 " ));
         compresser.finish();
         int len = compresser.deflate(output);
         System.out.println( " level via setLevel(): len= " + len+  "   "  +Arrays.toString(output));
    }
    public static void main (String[] args) throws java.lang.Exception
    {
            test1();
            test2();
    }
}
---------- END SOURCE ----------
Comments
The following first invocation of deflate() after setLevel() usually only tries to clean up the possible remaining bytes in the deflater (to flush out the compressed bytes with the "old" level). If the compression level is changed, the input available so far is compressed with the old level (and may be flushed); the new level will take effect only at the next call of deflate(). Either the implementation needs to be updated or the API for setLevel/Strategy() need to updated to clarify the behavior.
17-07-2013

I can reproduce this with jdk 6 and 7 and hence correct the affect versions.
17-07-2013