SVNKit内存泄漏:SVNLog.run()创建永远不会被杀死的线程

时间:2015-10-21 23:49:21

标签: java tomcat memory-leaks svnkit

我的Tomcat webapp在两个时间点之间向SVN查询提交:

    final SVNURL url = SVNURL.parseURIEncoded("svn+ssh://xxxx/xxxx/xxxx");

SVNSSHAuthentication sshCredentials = SVNSSHAuthentication.newInstance(
    Constants.SVN_USERNAME,
    Constants.PRIVATE_KEY,
    Constants.PRIVATE_KEY_PASS_PHRASE,
    Constants.SVN_PORT,
    Constants.ALLOW_CREDENTIALS_TO_BE_STORED,
    url,
    Constants.CREDENTIAL_IS_NOT_PARTIAL);

ISVNAuthenticationManager authManager = new BasicAuthenticationManager(new SVNAuthentication[] { sshCredentials });
SvnOperationFactory svnOperationFactory = new SvnOperationFactory();
try {

  svnOperationFactory.setAuthenticationManager(authManager);

  final SvnLog log = svnOperationFactory.createLog();
  log.addRange(SvnRevisionRange.create(SVNRevision.create(new Date(1444612639000l)), SVNRevision.create(new Date(1444737236000l))));
  log.setDiscoverChangedPaths(true);
  log.setLimit(100l);
  log.setReceiver(new ISvnObjectReceiver<SVNLogEntry>() {
    @Override
    public void receive(SvnTarget target, SVNLogEntry logEntry) throws SVNException {
      System.out.println(logEntry);
    }
  });
  log.setSingleTarget(SvnTarget.fromURL(url));
  log.run();
}
catch (SVNException e) {
  throw e;
} finally {
  svnOperationFactory.dispose();
}

问题:每次重新加载或重新部署webapp时,都会有一些线程未被杀死,导致永久生成中的重复类: enter image description here

这些是每次调用log.run()时创建的线程。你看到有两个组 - 第一组属于webapp的前一个实例 - 已经被停止 - 由于某种原因它们不会与webapp一起被杀死。 enter image description here

线程6和线程11的堆栈跟踪:

Thread dump at 5:11.060.359

* Thread group "main":

  Thread "Thread-6":
    at java.net.SocketInputStream.socketRead0(java.io.FileDescriptor, byte[ ], int, int, int)
    at java.net.SocketInputStream.read(byte[ ], int, int, int)
    at java.net.SocketInputStream.read(byte[ ], int, int)
    at com.trilead.ssh2.crypto.cipher.CipherInputStream.fill_buffer()
    at com.trilead.ssh2.crypto.cipher.CipherInputStream.internal_read(byte[ ], int, int)
    at com.trilead.ssh2.crypto.cipher.CipherInputStream.getBlock()
    at com.trilead.ssh2.crypto.cipher.CipherInputStream.read(byte[ ], int, int)
    at com.trilead.ssh2.transport.TransportConnection.receiveMessage(byte[ ], int, int)
    at com.trilead.ssh2.transport.TransportManager.receiveLoop()
    at com.trilead.ssh2.transport.TransportManager$1.run()
    at java.lang.Thread.run()

如果我注释掉log.run(),则不会创建线程,因此不会泄露任何资源。所以问题是因为log.run() - 不知何故,当webapp被杀死时线程没有被杀死。

代码末尾的

svnOperationFactory.dispose();似乎没有任何处置。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

根据我的经验,第三方软件的泄漏确实取决于版本。您的问题没有说明您所使用的SVNKit版本。所以作为响应的第一个第一个破解,我会问你是否使用最新版本的SVNKit。我一直在用SVNKit研究一些候选内存泄漏,包括:

  1. No dispose called on SVNClients
  2. Orphaned threads with svn+ssh connections
  3. 和其他一些人。但是,它们似乎都是旧版本的SVNKit,所以如果可能的话我会先尝试升级。