RFR: JDK-8142508: To bring j.u.z.ZipFile's native implementation to Java to remove the expensive jni cost and mmap crash risk
Seán Coffey
sean.coffey at oracle.com
Mon Dec 7 16:51:42 UTC 2015
Hi Sherman,
Nice work. It'll certainly help protect the VM from bad application
code. I've no major issues with the new code. Some comments below.
src/java.base/share/classes/java/util/zip/ZipFile.java
unused import :
> import java.nio.file.Path;
line 840 : This could be marked final
> private Key key;
line 914 : Same here (final)
> private static HashMap<Key, Source> files = new HashMap<>();
While in this class, could you also mark inflaterCache as final (line 451)
- String prop =
sun.misc.VM.getSavedProperty("sun.zip.disableMemoryMapping");
With this property removed, I think you'll need to update
src/java.base/share/classes/sun/misc/VM.java line 278 also. It becomes
redundant code.
We'll also need to log a sub-task to track doc updates to highlight that
this property is no longer relevant.
ZipFile : line 195 :
Objects.requireNonNull(charset, "charset");
You've changed the order of exception throwing here. To aid with a
possible backport (and behaviour), could you consider moving the check
to post the 'mode' checks ? If you can't, I'll just remember it when
backporting!
line 525 :
byte[] cen = zsrc.cen;
It might be no harm to insert a comment here saying that the caller
method must check for 'ensureOpen' ?
I think you need a ensureOpen check on the new initDataOffset() method.
You could hit an NPE otherwise. E.g. :
> ZipFile zf = new ZipFile(new File("/tmp/jtreg.zip"));
> ZipEntry ze = zf.getEntry("jtreg/release");
> InputStream is = zf.getInputStream(ze);
> zf.close();
> is.skip(1);
There might be room for a small improvement on the zerror method. Could
you pre-append the name of the File to each exception message via this
method ?
On the new test, are you planning to add this to the jtreg tests or will
it be
a manual stand alone ? It would have to be tuned down in terms of resources
if added to the auto-test list.
Regards,
Sean.
On 11/11/15 20:22, Xueming Shen wrote:
> Hi
>
> Please help review the changes for JDK-8142508 (third try)
>
> Issue: https://bugs.openjdk.java.net/browse/JDK-8142508
> webrev: http://cr.openjdk.java.net/~sherman/8142508/webrev
>
> Mainly to address the issues in current j.u.z.ZipFile implementation
> as listed
> below
>
> (1) The ZIP file format support code is in native C (shared with the
> VM via
> ZipFile.c -> zip_util.c). Any entry lookup, creation operation
> requires multiple
> round-trips of expensive jni calls.
>
> (2) The native C implementation which uses mmap to map in the central
> directory
> table appears to be a big risk of vm crash when the underlying
> jar file gets
> overwritten with new contents while it is still being used by
> other ZipFile. The
> crash reports keep coming in even after we have introduced in
> system flag
> to disable it (sun.zip.disableMemoryMapping).
>
> (3) The use of "filename + lastModified()" cache (zip_util.c) appears
> to be broken
> if the timestamp is in low resolution/precision
> (File.getModified() for example,
> might only have "second" ersolution on solaris/linux), and/or the
> file is being
> overwritten.
>
> The clean solution appears to bring the ZIP format support code
> completely from
> native to Java to remove the jni invocation cost and the mmap risk.
> Also to use
> the fileKey and lastModified from
> java.nio.file.attribute.BasicFileAttributes to have
> better/correct cache matching.
>
> Benchmark:
>
> This simple jmh measurement suggests a big boost of the performance of
> ZipFile.getEntry()/entries()/getStream() which are basically entry
> related
> accesses (the "open only" has some regression, which is expected as we
> switched from the mmap to simply read the cen table in into a byte[])
>
> http://cr.openjdk.java.net/~sherman/8142508/MyBenchmark.java
>
> # JDK9 base
>
> Benchmark Mode Cnt Score Error Units
> MyBenchmark.testEntries avgt 50 13.671 ± 0.385 ms/op
> MyBenchmark.testGetEntry avgt 50 17.414 ± 0.803 ms/op
> MyBenchmark.testGetStream avgt 50 42.398 ± 10.136 ms/op
> MyBenchmark.testOpen avgt 50 3.049 ± 0.094 ms/op
> MyBenchmark.testRead avgt 50 215.179 ± 9.926 ms/op
> MyBenchmark.testReadAll avgt 50 244.422 ± 19.375 ms/op
> --------------------------------------------------------------------------------------
>
> # JDK9 ZipFile without jni invocation
>
> Benchmark Mode Cnt Score Error Units
> MyBenchmark.testEntries avgt 50 6.436 ± 0.422 ms/op
> MyBenchmark.testGetEntry avgt 50 10.021 ± 0.699 ms/op
> MyBenchmark.testGetStream avgt 50 38.713 ± 16.687 ms/op
> MyBenchmark.testOpen avgt 50 3.288 ± 0.119 ms/op
> MyBenchmark.testRead avgt 50 220.653 ± 8.529 ms/op
> MyBenchmark.testReadAll avgt 50 249.798 ± 18.438 ms/op
> ---------------------------------------------------------------------------------------
>
>
> Test:
> http://cr.openjdk.java.net/~sherman/8142508/webrev/test/java/util/zip/ZipFile/TestZipFile.java.html
>
>
> Verified the new ZipFile runs as expected when the underlying jar/zip
> file get
> deleted/overwritten when the zip still be used. The "old" ZipFile
> fails to continue
> to work but no crash, and the "new" one works correctly on updated zip
> file
> without problem (The test runs a little long, have not decided if it
> should be
> checked in as unit test).
>
> -Sherman
>
More information about the core-libs-dev
mailing list