When using an alternative zlib implementation (in my case the implementation at https://github.com/jtkukunas/zlib) jdk/test/tools/pack200PackTestZip64.java test fails incorrectly.
The test fails with following exception:
java.util.zip.ZipException: invalid entry compressed size (expected 88 but got 89 bytes)
at java.util.zip.ZipOutputStream.closeEntry(ZipOutputStream.java:267)
at java.util.zip.ZipOutputStream.putNextEntry(ZipOutputStream.java:192)
at java.util.jar.JarOutputStream.putNextEntry(JarOutputStream.java:109)
at PackTestZip64.generateLargeJar(PackTestZip64.java:137)
at PackTestZip64.testPacking(PackTestZip64.java:55)
at PackTestZip64.main(PackTestZip64.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:110)
at java.lang.Thread.run(Thread.java:745)
Here is what happens :
The test generates a new jar file ( in generateLargeJar()) from existing files in golden.jar along with a large number of small dummy files.
Since the JarEntry's which are put in the new jar are read from the existing jar, the compressed size for them is set.
Here is the relevant code in generateLargeJar() -
for (JarEntry je : Collections.list(srcJar.entries())) {
copyTo.putNextEntry(je);
if (!je.isDirectory()) {
copyStream(srcJar.getInputStream(je), copyTo);
}
copyTo.closeEntry();
}
Later ZipOutputStream.closeEntry() validates the compressed size in the JarEntry by comparing it to number of bytes written,
if (e.csize != def.getBytesWritten()) {
throw new ZipException(
"invalid entry compressed size (expected " +
e.csize + " but got " + def.getBytesWritten() + " bytes)");
}
The above check fails, throwing an exception.
This is an error because the Zlib specification gives implementations a flexibility of choosing a string search algorithm, thus generating different bit streams.
A workaround is to reset the compressed size of 'JarEntry' before its added to the new jar, as shown below,
je.setCompressedSize(-1);
copyTo.putNextEntry(je);
The test fails with following exception:
java.util.zip.ZipException: invalid entry compressed size (expected 88 but got 89 bytes)
at java.util.zip.ZipOutputStream.closeEntry(ZipOutputStream.java:267)
at java.util.zip.ZipOutputStream.putNextEntry(ZipOutputStream.java:192)
at java.util.jar.JarOutputStream.putNextEntry(JarOutputStream.java:109)
at PackTestZip64.generateLargeJar(PackTestZip64.java:137)
at PackTestZip64.testPacking(PackTestZip64.java:55)
at PackTestZip64.main(PackTestZip64.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:110)
at java.lang.Thread.run(Thread.java:745)
Here is what happens :
The test generates a new jar file ( in generateLargeJar()) from existing files in golden.jar along with a large number of small dummy files.
Since the JarEntry's which are put in the new jar are read from the existing jar, the compressed size for them is set.
Here is the relevant code in generateLargeJar() -
for (JarEntry je : Collections.list(srcJar.entries())) {
copyTo.putNextEntry(je);
if (!je.isDirectory()) {
copyStream(srcJar.getInputStream(je), copyTo);
}
copyTo.closeEntry();
}
Later ZipOutputStream.closeEntry() validates the compressed size in the JarEntry by comparing it to number of bytes written,
if (e.csize != def.getBytesWritten()) {
throw new ZipException(
"invalid entry compressed size (expected " +
e.csize + " but got " + def.getBytesWritten() + " bytes)");
}
The above check fails, throwing an exception.
This is an error because the Zlib specification gives implementations a flexibility of choosing a string search algorithm, thus generating different bit streams.
A workaround is to reset the compressed size of 'JarEntry' before its added to the new jar, as shown below,
je.setCompressedSize(-1);
copyTo.putNextEntry(je);
- duplicates
-
JDK-8253952 Refine ZipOutputStream.putNextEntry() to recalculate ZipEntry's compressed size
-
- Resolved
-
- relates to
-
JDK-8253952 Refine ZipOutputStream.putNextEntry() to recalculate ZipEntry's compressed size
-
- Resolved
-