You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mina.apache.org by "tomaswolf (via GitHub)" <gi...@apache.org> on 2026/04/23 22:03:39 UTC
Re: [I] Threads leak when running from Executable Jar [mina-sshd]
tomaswolf commented on issue #743:
URL: https://github.com/apache/mina-sshd/issues/743#issuecomment-4308565800
I finally got around to debug this. I'm sorry about the long delay; I had too many other things on my plate.
Long story short: don't use `FileSystems.newFileSystem(URI, Map<String,?>,ClassLoader)`.
Instead use this work-around:
```
public class SftpClientNoLeak {
private static final FileSystemProvider SFTP_FILE_SYSTEMS = new SftpFileSystemProvider();
public static void main(String[] args) throws Exception {
var uri = args.length == 1 ? URI.create(args[0]) : URI.create(
// use: docker run -p 2200:22 -v path-to-file:/home/demo/sftp --rm -it emberstack/sftp
"sftp://localhost:2200/sftp/anyfile.txt"
);
for (int i = 0; i < 100; i++) {
var data = fetchData(uri, "demo", "demo");
System.out.println(Thread.getAllStackTraces().size() + " threads");
}
}
public static byte[] fetchData(URI url, String user, String pw) throws Exception {
URI uri = SftpFileSystemProvider.createFileSystemURI(url.getHost(), url.getPort(), user, pw);
try (FileSystem fs = SFTP_FILE_SYSTEMS.newFileSystem(uri, Map.of())) {
Path remotePath = fs.getPath(url.getPath());
return Files.readAllBytes(remotePath);
}
}
}
```
Full story:
Apache MINA SSHD assumes that the `SftpFileSystemProvider ` used by `FileSystems.newFileSystem()` was a singleton. But that works only if the class can be found via the system class loader or the platform class loader, and Java treats it as an "installed file system provider". See the javadoc of class `FileSystems`. In an executable JAR built by the spring-boot-maven-plugin, this is not the case.
If not present as an "installed file system provider", `FileSystems.newFileSystem()` then tries to find the provider though the service loader using the given class loader, in this case, the thread context classloader. That does find our `SftpFileSystemProvider` all right, and the file system gets created. But `FileSystems.newFileSystem()` then does _not_ remember that, and the next call to `FileSystems.newFileSystem()` will create another instance, and so on.
Each `SftpFileSystemProvider` instance creates an `SshClient` that will remain until the application exits. And each `SshClient` will create its own IO threads. So that's why the threads accumulate.
The solution for Apache MINA SSHD could be to publish only a stateless facade via Java SPI and let these facade instances use a true singleton provider behind the scenes.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org
For additional commands, e-mail: dev-help@mina.apache.org