I have a Spring Boot app that checks for files every 10s.
@Scheduled (fixedRateString = "10000")
public void foo ()
{
try
{
List <Path> ps = Files.list (Path.of ("mydir")).sorted ().collect (Collectors.toList ());
for (Path p : ps)
{
bar (p);
}
}
catch (Exception e)
{
System.out.println (e.getMessage ());
}
}
After about 1 month of permanent runtime, I see an exception:
too many open files
It disappears as soon as I restart the app.
Not sure if it is at the Files.list
or bar
.
But I do not have any reading/writing of files without closing. So I have no clue why this happens.
Any ideas? How can I prevent/monitor this?
Those are file descriptors, leaked because the Stream
isn't closing properly(Files.list
).
The Files.list(Path)
method returns a Stream<Path>
.
This stream must be closed with a try-with-resources
, not just a try-catch.
try (Stream<Path> stream = Files.list(Path.of("mydir"))) {
List<Path> ps = stream.sorted().collect(Collectors.toList());
for (Path p : ps)
bar(p);
} catch (Exception e) {
System.out.println(e.getMessage());
}
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
The
try
-with-resources statement is atry
statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. Thetry
-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implementsjava.lang.AutoCloseable
, which includes all objects which implementjava.io.Closeable
, can be used as a resource.