字符串的 Gzip 压缩在 java11 与 java17 中给出不同的结果

Sha*_*shi 1 java gzip scala java-17

我对字符串应用了 gzip 压缩test-string。当我将 Scala 2.13.8 与Java 11.0.13(Java HotSpot(TM) 64 位服务器 VM)一起使用时,会产生压缩字符串H4sIAAAAAAAAACtJLS7RLS4pysxLBwCFdJByCwAAAA==.

然而,当我在Java 17.0.4.1(OpenJDK 64 位服务器 VM)上使用 Scala 2.13.8 执行相同的压缩操作时,它会产生H4sIAAAAAAAA/ytJLS7RLS4pysxLBwCFdJByCwAAAA==.,这两个压缩字符串都正确解压缩以检索原始 string test-string

我认为这可能取决于默认压缩级别等几个因素:Java 11 和 Java 17 之间的默认压缩级别可能有所不同,从而导致同一输入产生不同的输出。算法改进:Java 17 中的 Gzip 实现可能已经过优化,导致压缩结果不同。 内部实现细节:Gzip 压缩的内部实现细节在 Java 11 和 Java 17 之间可能发生了变化,影响了压缩输出。

这背后的原因可能是什么?我附上下面的代码。

val bos = new ByteArrayOutputStream("test-string".length)
val b64os = new Base64OutputStream(bos)
val gzip = new GZIPOutputStream(b64os)
gzip.write("test-string".getBytes("UTF-8"))
gzip.close()
val compressed = new String(bos.toByteArray, "UTF-8")
bos.close()
compressed.trim
Run Code Online (Sandbox Code Playgroud)

nos*_*nos 9

如果我们以十六进制查看两个输出,我们就会得到这两条数据

1f8b08000000000000ff2b492d2ed12d2e29cacc4b0700857490720b000000
                  ^^
1f8b08000000000000002b492d2ed12d2e29cacc4b0700857490720b000000
                  ^^
Run Code Online (Sandbox Code Playgroud)

基本上 1 个字节从 0 变为 255(十六进制的 ff)。这是gzip 格式的操作系统标头,在 java 16 中根据以下内容从 0 更改为 255: https: //bugs.openjdk.org/browse/JDK-8244706