我正在使用WildFly 11 Final,并创建了以下EJB:
@Singleton
@Startup
public class MyDebug {
private static final MyStaticSingleton myStaticSingleton = new MyStaticSingleton();
}
现在,如果我重新部署应用程序并通过JVisualVm查看堆,则每次重新部署我都会看到一个MyStaticSingleton实例。 MyStaticSingleton的实例由不同的ClassLoader引用。
取消应用程序部署后,JavaEE应用程序的ClassLoader不会被丢弃是正常行为吗?
答案 0 :(得分:2)
很可能是由于应用程序的某些不当行为引起的泄漏。 实际上,这是一个相当普遍的问题。
主要问题不是单例实例的数量增加,而是类加载器的数量增加,因此加载的类的数量也增加(最终可能很大)。您可以使用javacore转储轻松证明这一点。
要解决这个问题,您必须找到一个对象,防止这些类加载器中的每一个都被丢弃,从而阻止所有已加载的类。
此类EE应用程序不当行为的一个众所周知的示例是将log4j与启用的关闭挂钩(默认情况下启用)一起使用。
更新
仅需确认,给定示例中的静态引用对象不会导致所提及的类加载器/本机内存泄漏。 而且,由于静态字段声明为final-它符合EJB规范。
正如TS所提到的,主要怀疑对象是连接池,它通过运行自己的线程来违反EJB规范。
在EE环境中使用线程,尤其是与上下文类加载器一起使用,是此类泄漏的典型原因。
答案 1 :(得分:0)
EJB 3.2规范(16.2.2)在这一点上很明确:您不能这样做!
企业bean一定不能使用读/写静态字段。允许使用只读静态字段。因此,建议将企业bean类中的所有静态字段都声明为final。
只需为您的单身人士使用常规字段,然后将创建内容移至@PostConstruct
。
如果单例也受管理,请在此字段上使用注入。