setContextClassLoader含义

时间:2011-03-03 16:03:59

标签: java multithreading tomcat java-ee

与此问题类似: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行,那么错误消息就会消失。

但我的问题是:是否有内存泄漏?如果是这样,我不想只是让警告消失,我想修复泄漏。我该怎么做?

感谢。

(另外,如果我将“//在这里做一些有限的东西”更改为“//在这里做一个无限数量的东西(即永远循环)”,那么在这种情况下确保没有内存泄漏的正确方法是什么?)

2 个答案:

答案 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部署的所有类。