19
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

DeflaterやInflaterを使うときに注意すること

Last updated at Posted at 2013-06-08

Deflate操作時に使用するjavaの標準ライブラリであるjava.util.zip.Deflaterjava.util.zip.InflaterはJNIで単にzlibを呼んでいるだけなので(少なくともOracle JRE/OpenJDKの場合)、newのタイミングでJVMの管理外の領域に少なくとも辞書窓サイズ分のメモリを確保する。Deflateの辞書窓サイズはだいたい32KiBぐらいある。
次のコードはJVMには大した影響を与えないが、あっさりJVMの外のシステムのメモリを枯渇させるだろう。

DeflateSample.java
public class DeflateSample {
  public static void main(String... args) {
    for (;;) {
      new java.util.zip.Deflater();
    }
  }
}

##対応
使い捨てでDeflater/Inflaterを使う場合は必ずend()を呼ぶ。または使い捨てず、可能な限りreset()して使いまわすようにする。

finalize()end()を呼び出しているので、GCが走れば解決はする。したがってend()しなかったとしても完全なメモリリークにはならない。
しかしDeflaterがJVM内部で必要とするメモリサイズに比べ、JVM外部で消費するメモリサイズのほうが圧倒的に大きいので、システムメモリが枯渇するより先にJVMのメモリが尽きてGCが走るだろうと思うのは幻想である。

なお、GZIPOutputStreamとGZIPInputStreamは内部でDeflater/Inflaterを生成しており、close()するまでend()を呼ばないので、必ずclose()しよう。

###おまけ
恐ろしいことにJavadoc上のend()の重要性はかなり曖昧だ。「実装の問題」ということなんだろうか。おかげでこの問題は自力で引き当てるまでなかなか気が付かない。

19
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?