Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/382.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SSH递归下载导致内存泄漏_Java_Recursion_Memory Management_Ssh_Memory Leaks - Fatal编程技术网

Java SSH递归下载导致内存泄漏

Java SSH递归下载导致内存泄漏,java,recursion,memory-management,ssh,memory-leaks,Java,Recursion,Memory Management,Ssh,Memory Leaks,我正在使用提供一个实用程序,为我的公司备份整个服务器数据 该应用程序是使用Java8和JavaFX2 我的问题是,我认为我的递归下载是错误的,因为我的程序RAM使用量在以秒为单位增长,而且似乎从未释放出来 这是我执行的操作顺序: 连接到远程服务器:正常 选择SFT频道->会话。openChannel(“sftp”):确定 正在检索本地目录->sftpChannel.cd(主目录):确定 列出目录内容->final Vector entries=sftpChannel.ls(“.”) 调用递归方法

我正在使用提供一个实用程序,为我的公司备份整个服务器数据

该应用程序是使用
Java8
JavaFX2

我的问题是,我认为我的递归下载是错误的,因为我的程序RAM使用量在以秒为单位增长,而且似乎从未释放出来

这是我执行的操作顺序:

  • 连接到远程服务器:正常
  • 选择SFT频道->
    会话。openChannel(“sftp”)
    :确定
  • 正在检索本地目录->
    sftpChannel.cd(主目录)
    :确定
  • 列出目录内容->
    final Vector entries=sftpChannel.ls(“.”)
  • 调用递归方法以:
    • if(entry.getAttrs().isDir())
      ->调用递归方法
    • else->这是一个文件,没有更多的子文件夹可供访问
    • 进程下载
  • 现在,我认为内存泄漏发生在下载部分:

  • 开始下载和检索输入流 最终的InputStream=sftpChannel.get(remoteFilePath,新的sftprogressMonitor())

  • 其中
    sftprogressmonitor()
    是一个提供进度监控的界面,我使用它来更新UI(progressbar)。此接口从不在内部引用inputstream,只是为了说明这一点。但它仍然是一个非静态匿名类,因此它确实持有对DownloadMethod作用域的引用

  • 下载时,我创建文件以保存并打开一个输出流,将下载的内容写入其中:

    final BufferedOutputStream bos=新的BufferedOutputStream(新的FileOutputStream(fileToSave))

  • 这是我在下载远程文件时写入文件的地方:

  • 代码:

    当然,一旦完成,我不会忘记关闭两条流:

    is.close(); //the inputstream from sftChannel.get()
    bos.close(); //the FileOutputStream
    
    正如你所理解的,我递归地处理这些操作,意思是:

  • 列出当前目录内容
  • 检查第一个条目
    • 如果是目录,请进入目录,然后执行1。
    • 这是一个文件,下载它
  • 检查第二个条目 等等
  • 多个测试显示完全相同的行为(在这些测试期间,要下载的内容保持完全相同)。这意味着我的内存使用量在以同样的速度增长

    [更新1] 我尝试了一种解决方案,让JSch写入
    FileOutputStream
    本身:

    final BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileToSave));
    sftpChannel.get(remoteFilePath, bos, new SftpProgressMonitor() 
    
    sftprogressmonitor.end()
    I close->
    bos.close()

    没有任何变化

    我还尝试列出所有文件,仍然是递归的,将它们各自的字节长度添加到
    专用长totalBytesToDownload
    中,我的程序内存保持非常稳定:在整个过程中只占用了20Mb(因为totalBytesToDownload不断增加)这证实了我的下载方法确实有问题


    如果我确实关闭了流,为什么GC不会收集它们?

    这将在指向层次结构的符号链接或硬链接上消失。要么使用
    rsync
    要么建立一个你复制的东西的集合,并感谢你@LevKuznetsov指出这一点,但在我的例子中,我忽略了所有符号链接。你所说的
    rscync
    是什么意思?
    rsync
    是一个Linux实用程序,它完全可以完成你正在做的事情。谷歌。即使您关闭了软链接,也无法判断您是否正在查看硬链接。@LevKuznetsov服务器正在运行Windows server,而我在Jsch中没有看到这样的方法:/可能是重复的
    final BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileToSave));
    sftpChannel.get(remoteFilePath, bos, new SftpProgressMonitor()