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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to