On Thu, 6 May 2021 08:05:12 GMT, Jason Zaugg <jza...@openjdk.org> wrote:
>> src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java line 1235: >> >>> 1233: synchronized(ch) { >>> 1234: return ch.position(pos).read(bb); >>> 1235: } >> >> I think it's okay to include the update to EntryInputStream, that part looks >> fine, as does the directly use of the FileChannel positional read. >> >> I'm still mulling over the case where ch is not a FileChannel as I would >> expected it to capture the existing position and restore it after the read. >> I think this is the degenerative case when the zip file is located in a >> custom file system that doesn't support FileChannel. In that case, >> positional read has to be implemented on the most basic SeekableByteChannel. >> It would only be observed when mixing positional read ops with other ops >> that depend on the current position. > > Here are all the references to `ch`. > > > this.ch = Files.newByteChannel(zfpath, READ); > ... > this.ch.close(); > ... > ch.close(); // close the ch just in case no update > ... > if (ch instanceof FileChannel fch) { > return fch.read(bb, pos); > } else { > synchronized(ch) { > return ch.position(pos).read(bb); > } > } > ... > long ziplen = ch.size(); > ... > ch.close(); > > > It appears the only position-dependent operation called `read(ByteBuffer)`. > This is performed together with the `pos` call within the `synchronized(ch)` > lock. I have confirmed that the non-`FileChannel` code path is exercised by existing tests. test/jdk/jdk/nio/zipfs/ZipFSTester.java includes a test that forms a file system based on a JAR that is itself an entry within another `ZipFileSystem`. Sample stacks: java.lang.Throwable: readFullyAt. ch.getClass=class jdk.nio.zipfs.ByteArrayChannel at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem.readFullyAt(ZipFileSystem.java:1234) at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem.readFullyAt(ZipFileSystem.java:1226) at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem$EntryInputStream.initDataPos(ZipFileSystem.java:2259) at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem$EntryInputStream.read(ZipFileSystem.java:2201) at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem$2.fill(ZipFileSystem.java:2151) at java.base/java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158) at ZipFSTester.checkEqual(ZipFSTester.java:858) at ZipFSTester.test1(ZipFSTester.java:259) java.lang.Throwable: readFullyAt. ch.getClass=class jdk.nio.zipfs.ByteArrayChannel at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem.readFullyAt(ZipFileSystem.java:1234) at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem$EntryInputStream.read(ZipFileSystem.java:2214) at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem$2.fill(ZipFileSystem.java:2151) at java.base/java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158) at ZipFSTester.checkEqual(ZipFSTester.java:858) at ZipFSTester.test1(ZipFSTester.java:259) This use case is not covered by the `ZipFSTester.test2`, a multi-threaded test. While looking at the test I noticed false warnings in the output: `read()/position() failed`. This did not actually fail the test. I investigated this and a) fixed the condition to deal with the edge case of zero-length entries and b) throw an "check failed" exception when the assertion fails. ------------- PR: https://git.openjdk.java.net/jdk/pull/3853