25
6

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.

Javaでファイルのclose忘れて失敗した話

Last updated at Posted at 2018-04-30

はじめに

Java何年もやっててclose忘れてエラー起こしたアホは私です。

発生した問題

開発中のサーバーで連続負荷テストを実施していると、時間がたつにつれてアプリケーションの動作がおかしくなる現象が発生した。
CPUやメモリの使用率に問題は見られず原因が分からないままだったが、1~2週間ほど放置し続けるとログに「もうファイル開けません」的なエラーを出してアプリケーションが死んでいた。
その後アプリケーションが開いているファイルディスクリプタ数を確認すると、1プロセスあたりに開けるファイルディスクリプタ数の上限に達しているのを確認した。

問題となったコード

return Files.list(Paths.get(dirPathStr)).map(path -> path.getFileName().toString())
            .collect(Collectors.toSet());

問題となったコードは上記。Stream APIを使用してディレクトリ内のファイル名一覧を返すメソッドだが、Files.list()でオープンしたディレクトリがcloseされていない。
closeを忘れてもGCによってメモリ自体は解放されると思うがファイルディスクリプタの方は解放されないようなので、実行されるたびにファイルディスクリプタの数が増え続けることになった。
ちなみに開発環境にEclipseを使っていると(Scannerクラス等)ファイルを開くクラスのインスタンスでcloseを忘れると警告を出してくれるが、(Eclipse 4.7時点において)上記コードは警告を出してくれない。何故……

修正したコード

try (Stream<Path> paths = Files.list(Paths.get(dirPathStr))) {
	return paths.map(path -> path.getFileName().toString()).collect(Collectors.toSet());
}

ちゃんとcloseするようにした。ファイルディスクリプタの増加も起きなくなり、アプリケーションも問題なく動作するようになった。

おわりに

以下教訓

  • テストするときはCPUやメモリ使用率以外も確認する
  • ちゃんとJavadoc確認する
  • IDEに頼りすぎない
25
6
1

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
25
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?