【问题标题】:SVNKit memory leak: SVNLog.run() creates thread that is never killedSVNKit 内存泄漏:SVNLog.run() 创建的线程永远不会被杀死
【发布时间】:2015-10-21 23:49:21
【问题描述】:

我的 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时,有几个线程没有被杀死,导致Permanent Generation中的类重复:

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

线程 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(); 似乎没有处理任何内容。

有什么想法吗?

【问题讨论】:

    标签: java tomcat memory-leaks svnkit


    【解决方案1】:

    根据我的经验,第三方软件中的漏洞确实取决于版本。您的问题并未说明您使用的是哪个版本的 SVNKit。所以作为第一次回复,我会问你是否使用最新版本的 SVNKit。我一直在研究一些使用 SVNKit 的候选内存泄漏,包括:

    1. No dispose called on SVNClients
    2. Orphaned threads with svn+ssh connections

    还有其他一些。但是,它们似乎都适用于旧版本的 SVNKit,所以如果可能,我会尝试先升级。

    【讨论】:

    • 我用的是tomcat 8,svnkit 1.8.11,都是最新版本。
    • 另一个愚蠢的问题:您是否在多个部署之间进行了堆转储,在每次部署后观察新创建的线程,确保这不是第一个/第二个创建更多线程的问题重新部署?
    • 是的,我在这个问题上花了 2 天时间,并且已经完成了书中的所有技巧 - 我确信这些线程是 SVNLog.run() 的产物
    • Fukuzawa,我认为您指的是 org.tmatesoft.svn.core.wc2.SVNLog 类对吗?我下载了源代码,并且有两个类名称 SVNLog - 因此问题。
    • @FukuzawaYukio,我在本地主机上查看了包的源代码。您提到您尝试过svnOperationFactory.dispose(),但无济于事。您是否尝试将 log.cancel() 添加到您的 finally 块或代码中的其他更可取的位置?
    猜你喜欢
    • 2019-01-31
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    • 2015-07-07
    • 2021-01-14
    • 2015-04-11
    • 1970-01-01
    • 2016-02-18
    相关资源
    最近更新 更多