The below test is on HPack dynamic table,
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import sun.net.httpclient.hpack.Decoder;
import sun.net.httpclient.hpack.DecodingCallback;
public class SimpleHeaderTableTest {
private static final DecodingCallback DEFAULT = (name, value) -> {
System.out.println(name + ": " + value);
};
public static void main(String[] args) {
Decoder decoder = new Decoder(80);
printTableSize(decoder); // maxSize=80, size=0
// Insert entry (h-a: v-a) into the dynamic table.
decoder.decode(hexToBuffer("4003682d6103762d61"), DEFAULT, false);
printTableSize(decoder); // maxSize=80, size=38
// Insert entry (h-b: v-b) into the dynamic table.
decoder.decode(hexToBuffer("4003682d6203762d62"), DEFAULT, false);
printTableSize(decoder); // maxSize=80, size=76
// Insert entry (h-cc: v-cc) into the dynamic table, and evict the entry (h-a: v-a).
decoder.decode(hexToBuffer("4004682d636304762d6363"), DEFAULT, false);
printTableSize(decoder); // maxSize=80, size=78
// Update table size to 50, and evict the entry (h-b: v-b)
decoder.decode(hexToBuffer("3f13"), DEFAULT, false);
printTableSize(decoder); // maxSize=50, size=40
}
private static void printTableSize(Decoder decoder) {
System.out.printf("maxSize=%s, size=%s%n", tableMaxSize(decoder), tableSize(decoder));
}
private static int tableSize(Decoder decoder) {
try {
return getTableSize(decoder, "size");
} catch (Exception e) {
throw new RuntimeException("Retrieve size failed.");
}
}
private static int tableMaxSize(Decoder decoder) {
try {
return getTableSize(decoder, "maxSize");
} catch (Exception e) {
throw new RuntimeException("Retrieve size failed.");
}
}
private static int getTableSize(Decoder decoder, String sizeField)
throws Exception {
Object headerTable = getHeaderTable(decoder);
Method method = headerTable.getClass().getDeclaredMethod(sizeField);
method.setAccessible(true);
return (int) method.invoke(headerTable);
}
private static Object getHeaderTable(Decoder decoder) throws Exception {
Field field = decoder.getClass().getDeclaredField("table");
field.setAccessible(true);
return (Object) field.get(decoder);
}
private static ByteBuffer hexToBuffer(String hex) {
return ByteBuffer.wrap(hexToBytes(hex));
}
private static byte[] hexToBytes(String hex) {
int len = hex.length();
byte[] bytes = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
bytes[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
+ Character.digit(hex.charAt(i + 1), 16));
}
return bytes;
}
}
The output is the following,
maxSize=80, size=0
h-a: v-a
maxSize=80, size=38
h-b: v-b
maxSize=80, size=76
h-cc: v-cc
maxSize=80, size=78
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
at java.lang.System.arraycopy(Native Method)
at sun.net.httpclient.hpack.HeaderTable$CircularBuffer.resize(HeaderTable.java:441)
at sun.net.httpclient.hpack.HeaderTable$Table.setCapacity(HeaderTable.java:373)
at sun.net.httpclient.hpack.HeaderTable.setMaxSize(HeaderTable.java:234)
at sun.net.httpclient.hpack.Decoder.resumeSizeUpdate(Decoder.java:333)
at sun.net.httpclient.hpack.Decoder.proceed(Decoder.java:125)
at sun.net.httpclient.hpack.Decoder.decode(Decoder.java:100)
at httpclient.hpack.SimpleHeaderTableTest.main(SimpleHeaderTableTest.java:33)
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import sun.net.httpclient.hpack.Decoder;
import sun.net.httpclient.hpack.DecodingCallback;
public class SimpleHeaderTableTest {
private static final DecodingCallback DEFAULT = (name, value) -> {
System.out.println(name + ": " + value);
};
public static void main(String[] args) {
Decoder decoder = new Decoder(80);
printTableSize(decoder); // maxSize=80, size=0
// Insert entry (h-a: v-a) into the dynamic table.
decoder.decode(hexToBuffer("4003682d6103762d61"), DEFAULT, false);
printTableSize(decoder); // maxSize=80, size=38
// Insert entry (h-b: v-b) into the dynamic table.
decoder.decode(hexToBuffer("4003682d6203762d62"), DEFAULT, false);
printTableSize(decoder); // maxSize=80, size=76
// Insert entry (h-cc: v-cc) into the dynamic table, and evict the entry (h-a: v-a).
decoder.decode(hexToBuffer("4004682d636304762d6363"), DEFAULT, false);
printTableSize(decoder); // maxSize=80, size=78
// Update table size to 50, and evict the entry (h-b: v-b)
decoder.decode(hexToBuffer("3f13"), DEFAULT, false);
printTableSize(decoder); // maxSize=50, size=40
}
private static void printTableSize(Decoder decoder) {
System.out.printf("maxSize=%s, size=%s%n", tableMaxSize(decoder), tableSize(decoder));
}
private static int tableSize(Decoder decoder) {
try {
return getTableSize(decoder, "size");
} catch (Exception e) {
throw new RuntimeException("Retrieve size failed.");
}
}
private static int tableMaxSize(Decoder decoder) {
try {
return getTableSize(decoder, "maxSize");
} catch (Exception e) {
throw new RuntimeException("Retrieve size failed.");
}
}
private static int getTableSize(Decoder decoder, String sizeField)
throws Exception {
Object headerTable = getHeaderTable(decoder);
Method method = headerTable.getClass().getDeclaredMethod(sizeField);
method.setAccessible(true);
return (int) method.invoke(headerTable);
}
private static Object getHeaderTable(Decoder decoder) throws Exception {
Field field = decoder.getClass().getDeclaredField("table");
field.setAccessible(true);
return (Object) field.get(decoder);
}
private static ByteBuffer hexToBuffer(String hex) {
return ByteBuffer.wrap(hexToBytes(hex));
}
private static byte[] hexToBytes(String hex) {
int len = hex.length();
byte[] bytes = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
bytes[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
+ Character.digit(hex.charAt(i + 1), 16));
}
return bytes;
}
}
The output is the following,
maxSize=80, size=0
h-a: v-a
maxSize=80, size=38
h-b: v-b
maxSize=80, size=76
h-cc: v-cc
maxSize=80, size=78
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
at java.lang.System.arraycopy(Native Method)
at sun.net.httpclient.hpack.HeaderTable$CircularBuffer.resize(HeaderTable.java:441)
at sun.net.httpclient.hpack.HeaderTable$Table.setCapacity(HeaderTable.java:373)
at sun.net.httpclient.hpack.HeaderTable.setMaxSize(HeaderTable.java:234)
at sun.net.httpclient.hpack.Decoder.resumeSizeUpdate(Decoder.java:333)
at sun.net.httpclient.hpack.Decoder.proceed(Decoder.java:125)
at sun.net.httpclient.hpack.Decoder.decode(Decoder.java:100)
at httpclient.hpack.SimpleHeaderTableTest.main(SimpleHeaderTableTest.java:33)