(1)The extra field for ZIP64 (and any other type of extra field data block) has the
format 
header ID (2 bytes)
data size (2 bytes)
data block
The "data size" is the "size of data following", which does NOT inlclude the
2 + 2 bytes for the headerID + data size.
We does it correct in ZipOutputStream.writeLOC/CEN, we do it correct in
ZipFileSystem.writeLOC(). But unfortunately it appears we accidently included
the 4 byte header (id + size) in ZipFileSystem.writeCEN(), as showed below
           if (csize >= ZIP64_MINVAL) {
                csize0 = ZIP64_MINVAL;
                elen64 += 8;                 // csize(8)
            }
            if (size >= ZIP64_MINVAL) {
                size0 = ZIP64_MINVAL;        // size(8)
                elen64 += 8;
            }
            if (locoff >= ZIP64_MINVAL) {
                locoff0 = ZIP64_MINVAL;
                elen64 += 8;                 // offset(8)
            }
            if (elen64 != 0)
                elen64 += 4;                 // header and data sz 4 bytes
            ...
            if (elen64 != 0) {
                writeShort(os, EXTID_ZIP64);// Zip64 extra
                writeShort(os, elen64);     // size of "this" extra block
                if (size0 == ZIP64_MINVAL)
                    writeLong(os, size);
                if (csize0 == ZIP64_MINVAL)
                    writeLong(os, csize);
                if (locoff0 == ZIP64_MINVAL)
                    writeLong(os, locoff);
            }
(2) ZipFileSystem.sync()
   OutputStream os = Files.newOutputStream(tmpFile, WRITE);
It appears we are not wrapping the "os" with a BufferedOutputSteam, which might slow
down the sync() when writing loc and cen tables, especially if we have lots of entries
in the archive.