通常在WildFly中取消部署时会卸载静态字段吗?

时间:2018-10-16 14:44:14

标签: java-ee ejb wildfly classloader

我正在使用WildFly 11 Final,并创建了以下EJB:

@Singleton
@Startup
public class MyDebug {
    private static final MyStaticSingleton myStaticSingleton = new MyStaticSingleton();
}

现在,如果我重新部署应用程序并通过JVisualVm查看堆,则每次重新部署我都会看到一个MyStaticSingleton实例。 MyStaticSingleton的实例由不同的ClassLoader引用。

取消应用程序部署后,JavaEE应用程序的ClassLoader不会被丢弃是正常行为吗?

2 个答案:

答案 0 :(得分:2)

很可能是由于应用程序的某些不当行为引起的泄漏。 实际上,这是一个相当普遍的问题。

主要问题不是单例实例的数量增加,而是类加载器的数量增加,因此加载的类的数量也增加(最终可能很大)。您可以使用javacore转储轻松证明这一点。

要解决这个问题,您必须找到一个对象,防止这些类加载器中的每一个都被丢弃,从而阻止所有已加载的类。

此类EE应用程序不当行为的一个众所周知的示例是将log4j与启用的关闭挂钩(默认情况下启用)一起使用。

更新

仅需确认,给定示例中的静态引用对象不会导致所提及的类加载器/本机内存泄漏。 而且,由于静态字段声明为final-它符合EJB规范。

正如TS所提到的,主要怀疑对象是连接池,它通过运行自己的线程来违反EJB规范。

在EE环境中使用线程,尤其是与上下文类加载器一起使用,是此类泄漏的典型原因。

答案 1 :(得分:0)

EJB 3.2规范(16.2.2)在这一点上很明确:您不能这样做!

  

企业bean一定不能使用读/写静态字段。允许使用只读静态字段。因此,建议将企业bean类中的所有静态字段都声明为final。

只需为您的单身人士使用常规字段,然后将创建内容移至@PostConstruct。 如果单例也受管理,请在此字段上使用注入。