我正在使用JSch提供一个实用程序来备份我公司的整个服务器数据。
使用Java 8
& JavaFX 2
我的问题是我相信我的递归下载是错误的,因为我的程序RAM使用率在第二天增长,似乎永远不会释放。
这是我执行的操作的顺序:
session.openChannel("sftp")
:好的sftpChannel.cd(MAIN_DIRECTORY)
:好的final Vector<ChannelSftp.LsEntry> entries= sftpChannel.ls(".");
if (entry.getAttrs().isDir())
- &GT;调用递归方法现在,我认为下载部分发生了内存泄漏:
final InputStream = sftpChannel.get(remoteFilePath,new SftpProgressMonitor());
其中SftpProgressMonitor()
是提供进度监控的界面,我用它来更新UI(进度条)。此接口从不在内部引用输入流只是为了清楚说明。但它仍然是一个非静态的匿名类,因此它确实包含对DownloadMethod范围的引用。
在下载时,我创建要保存的文件并打开 OutputStream 以将下载的内容写入其中:
final BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileToSave));
这是我在下载远程文件时写入文件的地方:
代码:
int readCount;
final byte[] buffer = new byte[8 * 1024];
while ((readCount = is.read(buffer)) > 0) {
bos.write(buffer, 0, readCount);
bos.flush();
}
当然,一旦完成,我不会忘记关闭两个流:
is.close(); //the inputstream from sftChannel.get()
bos.close(); //the FileOutputStream
因此,您可以理解我递归处理这些操作意味着:
多个测试显示完全相同的行为(并且在这些测试期间下载的内容保持完全相同)。这意味着我的内存使用量会以同样的速度增长。
我尝试了一个解决方案,让我让JSch写入FileOutputStream
本身:
final BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileToSave));
sftpChannel.get(remoteFilePath, bos, new SftpProgressMonitor()
在SftpProgressMonitor.end()
我关闭 - &gt; bos.close()
。
完全没有改变。
我还尝试按递归方式列出所有文件,将它们各自的字节长度添加到private long totalBytesToDownload
,我的程序内存保持非常稳定:在整个过程中只占20Mb(在totalBytesToDownload持续增加的帐户上)确认我的下载方法确实有问题。
如果我关闭我的溪流,为什么GC不会收集它们?