Ich sehe eine seltsame Situation mit kleinen Ausgabepuffern mit Java 8u45 und der java.util.Deflater.deflate(byte[] b, int off, int len, int flush)
Methode, wenn mit kleinen Ausgabepuffern verwendet.Deflater.Deflate und kleine Ausgabepuffer
(Ich arbeite an einigen Code Low Level-Networking zu WebSocket anstehenden permessage-deflate
Erweiterung im Zusammenhang, so kleine Puffer sind für mich eine Realität)
Der Beispielcode:
package deflate;
import java.nio.charset.StandardCharsets;
import java.util.zip.Deflater;
public class DeflaterSmallBufferBug
{
public static void main(String[] args)
{
boolean nowrap = true;
Deflater deflater = new Deflater(Deflater.DEFAULT_COMPRESSION,nowrap);
byte[] input = "Hello".getBytes(StandardCharsets.UTF_8);
System.out.printf("input is %,d bytes - %s%n",input.length,getHex(input,0,input.length));
deflater.setInput(input);
byte[] output = new byte[input.length];
// break out of infinite loop seen with bug
int maxloops = 10;
// Compress the data
while (maxloops-- > 0)
{
int compressed = deflater.deflate(output,0,output.length,Deflater.SYNC_FLUSH);
System.out.printf("compressed %,d bytes - %s%n",compressed,getHex(output,0,compressed));
if (compressed < output.length)
{
System.out.printf("Compress success");
return;
}
}
System.out.printf("Exited compress (maxloops left %d)%n",maxloops);
}
private static String getHex(byte[] buf, int offset, int len)
{
StringBuilder hex = new StringBuilder();
hex.append('[');
for (int i = offset; i < (offset + len); i++)
{
if (i > offset)
{
hex.append(' ');
}
hex.append(String.format("%02X",buf[i]));
}
hex.append(']');
return hex.toString();
}
}
Im obigen Fall , Ich versuche, komprimierte Bytes für die Eingabe "Hello"
mit einem Ausgabepuffer von 5 Bytes Länge zu generieren.
würde ich das folgende resultierende Bytes annehmen:
buffer 1 [ F2 48 CD C9 C9 ]
buffer 2 [ 07 00 00 00 FF ]
buffer 3 [ FF ]
Welche
[ F2 48 CD C9 C9 07 00 ] <-- the compressed data
[ 00 00 FF FF ] <-- the deflate tail bytes
jedoch als
übersetzt, wennDeflater.deflate()
mit einem kleinen Puffer verwendet wird, ist das normal Schleife bei 5 Byte unendlich weiter komprimierten Daten (scheint nur bei Puffern von 5 Bytes oder niedriger zu manifestieren).
resultierender Ausgang die oben Demo läuft ...
input is 5 bytes - [48 65 6C 6C 6F]
compressed 5 bytes - [F2 48 CD C9 C9]
compressed 5 bytes - [07 00 00 00 FF]
compressed 5 bytes - [FF 00 00 00 FF]
compressed 5 bytes - [FF 00 00 00 FF]
compressed 5 bytes - [FF 00 00 00 FF]
compressed 5 bytes - [FF 00 00 00 FF]
compressed 5 bytes - [FF 00 00 00 FF]
compressed 5 bytes - [FF 00 00 00 FF]
compressed 5 bytes - [FF 00 00 00 FF]
compressed 5 bytes - [FF 00 00 00 FF]
Exited compress (maxloops left -1)
Wenn Sie die Eingabe/Ausgabe von mehr als 5 Bytes machen dann scheint das Problem weg zu gehen. (So stellen Sie die Eingabezeichenfolge "Hellox"
diese für sich selbst zu testen)
Ergebnisse des Puffers 6 Bytes machen (Eingang als "Hellox"
)
input is 6 bytes - [48 65 6C 6C 6F 78]
compressed 6 bytes - [F2 48 CD C9 C9 AF]
compressed 6 bytes - [00 00 00 00 FF FF]
compressed 5 bytes - [00 00 00 FF FF]
Compress success
Auch diese Ergebnisse sind wenig schrullig mir, wie es scheint sind 2 deflate Tail-Byte-Sequenzen vorhanden.
Also meine ich meine ultimative Frage ist, vermisse ich etwas über die Deflater
Verwendung, die für mich seltsam macht, oder zeigt dies auf einen möglichen Fehler in der JVM Deflater
Implementierung selbst?
Update: 7. August 2015
Diese Entdeckung als bugs.java.com/JDK-8133170 angenommen wurde
Dang! Mark Adler hat auf meine Frage geantwortet, es ist schwer, eine autoritativere Antwort als diese zu bekommen. :-) –
Ich denke, ich sollte einen Apidoc-Fehler bei Oracle einreichen, um diesen Leckerbissen der Deflater-Dokumentation hinzuzufügen. Scheint nützlich zu wissen. –
Es sollte als "Fehler" betrachtet werden, oder? Warum macht zlib das? Um eine Flagge zu speichern? – ZhongYu