【发布时间】:2012-03-08 03:38:20
【问题描述】:
编辑:
我在我的 web 应用程序中发现了类加载器泄漏。 它归结为第 3 方库通过 JNDI 的 COS 命名服务初始化 CORBA,而不是公开调用以干净地关闭 JNDI 的上下文。这留下了一些 CORBA 相关线程和其他资源引用我的 webapp 类加载器并防止它被垃圾收集。这会导致 OutOfMemory Error: PermGen after few redeploys/reloads。
现在我增加了 JVM 中的 PermGen 内存,它使服务器崩溃之间的间隔更长。这显然不是一种解决方法,而是一种解决方法(在这方面也是一个糟糕的解决方法)。
我想我的问题是有什么方法可以在不引用 JNDI 上下文的情况下干净地关闭它。我的直觉告诉我没有,但也许我不知道 JNDI 的一些神奇功能可以让我掌握那个上下文。
因此,第 3 方库初始化 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 资源保留在类加载器上。我想我可以尝试用一些清理方法来寻找它们并以这种方式释放类加载器,但我希望有一些更清洁的解决方案。
为了清楚起见,第 3 方库是封闭源代码,我无法真正更改它。从背后的公司获得支持也是不可行的选择。
【问题讨论】:
-
(这不是答案,因此是评论)...我个人会要求第 3 方 API 的开发人员修复他们的烂摊子。同时,您可以通过使用更大的 PermGen 或使用 不是 Oracle/Sun 的 JVM 来缓解问题,因为 PermGen,IIRC,是 Oracle/太阳特异性。 (这就是回忆:我记得在几乎找不到任何关于该主题的信息的日子里,我自己发现了一些可怕的 Tomcat + Sun JVM + Hibernate permgen 问题;) 那时我们“修复了“我们的问题是切换到 Resin IIRC(真的是很多年前)。
-
不幸的是,第 3 方开发者不存在 :)。这是我们的应用程序需要集成的遗留系统。但除此之外,我不确定问题是否直接出在图书馆中。就像我提到的,线程实际上是由 CORBA 子系统创建的,所以我想任何使用 CORBA 的库都会触发创建该线程。也就是说,我绝不是 CORBa 专家。不幸的是,更改应用服务器也不行。
-
作为一个糟糕的解决方法,可以节省您的时间,您可以将创建更大 PermGen 的参数传递给 Oracle/SUn JVM... 像这样:-XX:MaxPermSize=512m 当然是只是一个临时的解决方法。 Tomcat 6 的 "Find Leaks" 选项怎么样(例如,您可以在 Tomcat 管理器 webapp 中调用它),它是否也发现了相同的泄漏?
-
是的,我们已经应用了糟糕的解决方法。这延长了崩溃之间的间隔......虽然不理想,但总比没有好。至于“查找泄漏”,它只是告诉您哪个应用程序泄漏,而不是导致泄漏的原因,更不用说如何修复它:)。但它会检测到泄漏的应用程序。
-
在 JEE 应用服务器上,ORB.init 调用可能会导致问题。根据 corba 规范 ORB.init(args, null) 将创建一个新的 ORB 实例。创建 ORB 实例时,它将创建 5 个线程(4 个 ListenerThreads 和 1 个 ReaderThread)。只有当 ORB 实例被销毁时,这些线程才会被销毁。我们在第 3 方库中调用 ORB.init 时遇到了这个问题。创建 300 多个 ORB 和 1500 多个线程后,本机内存耗尽。测试表明,将 ORB.init 调用更改为 jndi (java:comp/ORB) 查找是解决方案。