1
0

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 3 years have passed since last update.

Files.listやFiles.walkやFiles.findの戻り値であるStream<Path>はクローズしないと、Too many open files が発生する

Last updated at Posted at 2021-01-31

Files.listFiles.walkFiles.findの戻り値であるStream<Path>DirectoryStreamをラップしたもので、利用後は必ずcloseする必要があります。このことはJavaDocにも以下の通りに記述されています。

返されるストリームは、1つ以上のDirectoryStreamをカプセル化します。ファイル・システム・リソースのタイムリな破棄が必要な場合は、try-with-resources構文を使用して、ストリーム操作の完了後にストリームのcloseメソッドが呼び出されるようにしてください。クローズされたストリームに対して操作すると、結果としてIllegalStateExceptionが発生します。

ではDirecotryStreamのラッパーであるStream<Path>closeしない場合、どうなるでしょうか? 以下のコードはFiles.listcloseせずに呼び出し続けるものです。

Main.java
public class Main {
    public static void main(String[] args) throws IOException {
        while (true) {
            Files.list(Paths.get("/dev")).collect(Collectors.toList());
        }
    }
}

これを実行してみると、以下のような例外が発生します。

Exception in thread "main" java.nio.file.FileSystemException: /dev: Too many open files
        at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:100)
        at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
        at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116)
        at java.base/sun.nio.fs.UnixFileSystemProvider.newDirectoryStream(UnixFileSystemProvider.java:432)
        at java.base/java.nio.file.Files.newDirectoryStream(Files.java:471)
        at java.base/java.nio.file.Files.list(Files.java:3698)
        at list.Main.main(Main.java:11)

Too many open files というメッセージからもわかる通り、Stream<Path>を明示的にクローズしないと、ファイルディスクリプタがオープンしたままになって、そのうちにプロセスのファイルディスクリプタの上限に達してしまいます。

よってJavaDocに書かれてある通り、Stream<Path>は使い終わったら、明確にクローズする必要があります。

Main.java
public class Main {
    public static void main(String[] args) {
        try (Stream<Path> ds = Files.list(Paths.get("/dev"))) {
            List<Path> paths = ds.collect(Collectors.toList());
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }
}

環境情報

C:\>javac -version
javac 11.0.3
C:\>java -version
openjdk version "11.0.3" 2019-04-16
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.3+7)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.3+7, mixed mode)
1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?