2

我在一个地方,服务器(tomcat)上相同的war文件的重复部署-取消部署操作导致PermGen OutOfMemoryError。我的目标是确保在未部署战争时卸载所有类。

这是我的一堂课:

public class ClassA {
//static variables & methods
//instance variables & methods

    private EnumInsideClassA myState = EnumInsideClassA.VALUE1;

    private enum EnumInsideClassA
    {
        VALUE1,
        VALUE2
    }
}

当我清除 ClassA 的所有引用时,我看不到 ClassA,并且在取消部署战争时将其卸载。但是,我仍然看到枚举引用并且 ClassA$EnumInsideClassA 没有被卸载。

'myState' 实例变量没有 getter,它只会与 ClassA 一起使用

任何帮助表示赞赏

4

2 回答 2

1

但是,我仍然看到枚举引用并且 ClassA$EnumInsideClassA 没有被卸载。

如果您可以看到enum参考资料,您应该能够看到它们在哪里。现在将有一些枚举引用可通过枚举类的隐藏静态字段访问,但这些应该是循环引用并且不应该导致enum保持可访问。看看enum其他地方有没有参考。

于 2012-04-08T09:29:50.060 回答
1

问题似乎是类加载器没有卸载枚举实例。我有一个测试 servlet 项目,它只有一个枚举。它也不必是私有或内部类枚举,但它确实需要至少被引用一次,以便创建实例。jvm 似乎没有将枚举视为任何特殊的东西,这似乎是真的。我在静态实例中看到了同样的问题(即自定义类的静态实例在类加载器卸载时没有得到垃圾收集)。

我尝试了各种 -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled 都没有成功。这可能是 JVM 特定的(我在 Mac OS X 上,他们似乎没有这些选项,但 -Xincgc 也不起作用:http: //developer.apple.com/library/mac/#documentation /Java/Reference/Java_VMOptionsRef/Articles/JavaVirtualMachineOptions.html)。有很多关于 stackoverflow 的信息,例如处理“java.lang.OutOfMemoryError: PermGen space”错误

可能对这个特定问题(servlet 重新部署)的最佳解决方法是将所有枚举放在一个不需要卸载的 jar 中。

FIY:我的环境是 Mac OS X 10.6.8,Java 1.6.0_31

于 2012-06-12T19:48:58.440 回答