与此问题类似:setContextClassLoader implications,我正在尝试清除有关内存泄漏的警告。具体来说,我有一个代码如下的servlet:
public void doGet(HttpServletRequest httpRequest,
HttpServletResponse httpResponse) throws ServletException, IOException {
class BasicThread extends Thread {
public void run() {
// Do a finite amount of stuff here
}
}
Thread thread = new BasicThread();
//thread.setContextClassLoader(null);
thread.start();
}
这篇文章:http://wiki.apache.org/tomcat/MemoryLeakProtection#cclThreadSpawnedByWebApp表示如果我取消注释setContextClassLoader行,那么错误消息就会消失。
但我的问题是:是否有内存泄漏?如果是这样,我不想只是让警告消失,我想修复泄漏。我该怎么做?
感谢。
(另外,如果我将“//在这里做一些有限的东西”更改为“//在这里做一个无限数量的东西(即永远循环)”,那么在这种情况下确保没有内存泄漏的正确方法是什么?)
答案 0 :(得分:2)
如果以下情况属实,这只是一个真正的问题。 1.线程永不停止,如果线程永不停止,则没有GC根,ClassLoader
永远不会被垃圾收集。 2.您的应用程序正在进行热部署,那么您一定要考虑到这一点。
潜在的问题是,当您要取消部署和重新部署时,应用程序服务器将希望GC为WAR的类加载器。如果WAR创建了一个强引用WAR类加载器的Thread并且Thread没有完成,则classlodaer永远不会收集垃圾,最终你会看到内存不足:Permagen。
如果为每个部署重新启动服务器(和JVM),则问题不会显现。
我仔细阅读了您发布的文章,并准确描述了我的建议
严重:出现了一个Web应用程序 已经开始一个名为的线程 [leakingThread]但未能停止 它。这很有可能创造一个 记忆泄漏。
对于更多的参考点,我问了一个关于类加载器泄漏的类似question。
答案 1 :(得分:1)
注意,一般来说,这是一个糟糕的设计。我可以通过执行一堆get调用轻松地让你的web服务器崩溃(直到你有这么多正在运行的线程,应用程序崩溃)。你应该总是在这种情况下使用线程池。
如果您将其设置为使用线程池,并且您根据webapp的生命周期管理线程池,那么您应该没有任何问题(例如,当重新(un)部署webapp时,相关线程池应该关闭)。
另一方面(忽略线程太多的问题),如果你希望线程超出webapp的生命周期,那么你应该清除上下文类加载器,因为可能这个线程与webapp并不真正相关无论如何都有问题(因为它有不同的生命周期)。
最后,为了直接回答你的一个问题,清除上下文类加载器的含义是,正在运行的线程可能无法访问为启动它的webapp部署的所有类。