// Presented for your consideration
public static void main(String[] args) throws Exception {
while (true) {
try (var b = new ByteArrayOutputStream();
var d = new DeflaterOutputStream(b, new Deflater(Deflater. BEST_SPEED))) {
d.write(new byte[1]);
}
}
}
public static void main(String[] args) throws Exception {
while (true) {
try (var b = new ByteArrayOutputStream();
var d = new DeflaterOutputStream(b, new Deflater(Deflater. BEST_SPEED))) {
d.write(new byte[1]);
}
}
}
This is one of the nominees in "Wolf-in-sheep's-clothing code" category. One of the easiest ways to throw the whole system into thrashing, invoking OOM-killer, or just OOME-ing JVM (if you are lucky). (Aside: don't you dare ask this on Java interviews.)
Everything is awful:
a) Deflater carries native zlib buffers, which are cleared either by a finalizer or by an explicit call to Deflater.end();
b) Finalizers are not executed, because allocation pressure is very low, so no GC cycle happens, so no finalization either;
a) Deflater carries native zlib buffers, which are cleared either by a finalizer or by an explicit call to Deflater.end();
b) Finalizers are not executed, because allocation pressure is very low, so no GC cycle happens, so no finalization either;
c) DeflaterOS calls Deflater.end(), but only for Deflaters instantiated internally. Here, we are passing external Deflater to DeflaterOS, because we want to override its compression level;
d) Deflater is not AutoCloseable, so we cannot use it in try-with-resources;
d) Deflater is not AutoCloseable, so we cannot use it in try-with-resources;
For me, this test runs into OOM-killer in about a minute on my 128G machine. This thread was inspired by a recent Shenandoah support discussion, which turned out to be not about Shenandoah per se.
Hot tip: make sure your Inflaters/Deflaters end().
Or at least make sure their population does not grow indefinitely (pooling, right?), for example if you want to reset/reuse them. See for example ZipFileSystem: https://github.com/openjdk/jdk/blob/master/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java#L2299-L2325
Or at least make sure their population does not grow indefinitely (pooling, right?), for example if you want to reset/reuse them. See for example ZipFileSystem: https://github.com/openjdk/jdk/blob/master/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java#L2299-L2325