CORBA + Tomcat 6 + Webapp类加载器泄漏

时间:2012-02-16 17:49:25

标签: java tomcat corba

修改

我在webapplication中发现了classloader泄漏。 它归结为第三方库通过JNDI的COS命名服务初始化CORBA,而不是公开调用干净地关闭JNDI的上下文。这留下了一些与CORBA相关的线程和其他资源引用我的webapp类加载器并防止它被垃圾收集。这会导致OutOfMemory Error:PermGen在重新配置/重新加载后很少。

现在我增加了JVM中的PermGen内存,它使服务器之间的间隔时间更长。这显然不是一种解决方法,而是一种解决方法(对于这个问题而言是一种糟糕的方法)。

我想我的问题是有什么方法可以干净地关闭JNDI上下文而不保留对它的引用。我的直觉告诉我没有,但也许我不知道JNDI的一些神奇功能可以让我掌握这种背景。

因此,第三方库初始化CORBA对象的方式就是这样的(为了简洁起见,省略了异常处理和其他细节):

private CorbaObjectAggregate initCorba() {
    InitialContext ctx = null;
    CorbaObjectAggregate corbaObjects = new CorbaObjectAggregate();
    ORB orb = null;
    Properties env = getContextEnvironment();
    String[] args = null;
    orb = ORB.init(args, null);
    env.put("java.naming.corba.orb", orb);
    ctx = new InitialContext(env);
    //a bunch of object lookups follow
    corbaObjects.someCorbaObjectReference = (SomeCorbaObjectClass) ctx.lookup("somePaht");
    return corbaObjects;
}

因此,在该方法完成执行后,ctx的引用消失了......

我尝试手动停止线程,但没有修复漏洞。我想还有其他一些corba资源保存在classloader上。我想我可以尝试用一些清理方法捕获它们并以这种方式释放类加载器,但我希望能有一些更清晰的解决方案。

为了清楚起见,第三方库是封闭源代码,我无法真正改变它。从背后的公司获得支持也是不可行的选择。

1 个答案:

答案 0 :(得分:1)

修复这个问题会很棘手。可能存在两个问题: - 从JAR加载的类,包含对web-app类加载器的引用 - 由该进程启动的线程,将web-app类加载器作为其上下文类加载器。

以下几行应该有所帮助:

  1. 将JAR移至$ CATALINA_BASE / lib。这意味着类由公共类加载器加载。不利的一面是,每个Web应用程序都可以看到它们并共享它们。

  2. 找出应用程序中触发初始化的位置。在该代码执行之前,将线程上下文类加载器设置为系统类加载器(或当前(web-app)类加载器的父级)并在init调用之后重置线程上下文类加载器。这应该意味着创建的任何线程都没有web-app类加载器作为上下文类加载器。

  3. 如果在其他时间点创建线程,修复此问题可能会非常棘手,非常快。

    有些背景可能有助于了解正在发生的事情,请参阅: http://people.apache.org/~markt/presentations/2010-11-04-Memory-Leaks-60mins.pdf

    要查看Tomcat内部处理这些问题的事情,请参阅: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java?view=annotate