Tôi thấy một tình huống lạ với bộ đệm đầu ra nhỏ với Java 8u45 và phương pháp java.util.Deflater.deflate(byte[] b, int off, int len, int flush)
khi được sử dụng với bộ đệm đầu ra nhỏ.Deflater.deflate và bộ đệm đầu ra nhỏ
(Tôi đang làm việc trên một số mã mạng ở mức độ thấp liên quan đến mở rộng permessage-deflate
sắp tới WebSocket của, bộ đệm quá nhỏ đang trở thành hiện thực đối với tôi)
Đoạn mã ví dụ:
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();
}
}
Trong trường hợp trên , Tôi đang cố gắng tạo ra các byte nén cho đầu vào "Hello"
bằng cách sử dụng một bộ đệm đầu ra có chiều dài 5 byte.
tôi sẽ giả định các byte kết quả sau:
buffer 1 [ F2 48 CD C9 C9 ]
buffer 2 [ 07 00 00 00 FF ]
buffer 3 [ FF ]
nào dịch là
[ F2 48 CD C9 C9 07 00 ] <-- the compressed data
[ 00 00 FF FF ] <-- the deflate tail bytes
Tuy nhiên, khi Deflater.deflate()
được sử dụng với một bộ đệm nhỏ, vòng bình thường này tiếp tục vô hạn ở mức 5 byte nén dữ liệu (dường như chỉ hiển thị ở bộ đệm 5 byte trở xuống).
Kết quả đầu ra của chạy demo trên ...
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)
Nếu bạn thực hiện các đầu vào/đầu ra lớn hơn 5 byte thì vấn đề dường như biến mất. (Chỉ cần chắc chuỗi đầu vào "Hellox"
để kiểm tra này cho chính mình)
Kết quả của dung dịch đệm 6 byte (đầu vào như "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
Ngay cả những kết quả này có chút kỳ quặc đối với tôi, vì nó dường như có 2 deflate chuỗi byte-byte hiện nay. Vì vậy, tôi đoán câu hỏi cuối cùng của tôi là, tôi thiếu một cái gì đó về việc sử dụng Deflater
mà làm điều kỳ lạ đối với tôi, hoặc là điều này chỉ vào một lỗi có thể có trong việc thực hiện JVM Deflater
chính nó?
Cập nhật: ngày 07 tháng 8 năm 2015
Phát hiện này đã được chấp nhận như bugs.java.com/JDK-8133170
Dang! Mark Adler trả lời câu hỏi của tôi, thật khó để có được câu trả lời có thẩm quyền hơn thế này. :-) –
Đoán tôi nên gửi một lỗi apidoc với Oracle để thêm miếng ngon này vào tài liệu Deflater. Có vẻ hữu ích để biết. –
Nó nên được coi là một "lỗi", phải không? Tại sao zlib làm điều đó? Để lưu cờ? – ZhongYu