【问题标题】:Are static fields normally unloaded on undeployment in WildFly?在 WildFly 中取消部署时,静态字段通常会被卸载吗?
【发布时间】:2023-03-26 05:05:02
【问题描述】:

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

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

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

在卸载应用程序后,JavaEE 应用程序的类加载器没有被丢弃是正常行为吗?

【问题讨论】:

  • 我很好奇你为什么要在@Singleton 中放置一个静态属性。由于您的封闭实例是作为单例管理的,因此您“应该”能够将其标记为私有(如果您确实需要,则为最终实例)。您的静态引用可能导致封闭的“先前”实例没有被垃圾收集(即使 ejb 容器不再管理它)。
  • 为了方便调试,我把@Singleton注解放在那里。这样,我可以确保在部署时立即加载类,以便在连续几次重新部署后立即检查堆。

标签: jakarta-ee ejb wildfly classloader


【解决方案1】:

您的应用程序的某些不当行为很可能会导致泄漏。 事实上,这是一个相当普遍的问题。

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

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

EE 应用程序这种不当行为的一个众所周知的例子是使用 log4j 和启用的关闭挂钩(默认启用)。

更新

只是为了确认,给定示例中的静态引用对象不会导致提到的类加载器/本机内存泄漏。 此外,由于静态字段声明为 final - 它符合 EJB 规范。

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

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

【讨论】:

  • 非常感谢。我对那个log4j的例子很好奇,不知道哪里有详细解释?
  • 关于类加载器的根目录,是的,我做了一些核心转储并检查了它们。拥有过时类加载器的一个根来自 C3P0,它是休眠中的连接池提供程序:ThreadPoolAsynchronousRunner$PoolThread,它扩展了 Thread。这是由 Hibernate / C3P0 完成的,我不知道如何阻止这种行为。
  • 请记住,无状态 EJB 中的非托管实例可能是一个问题(单例和有状态可以避免这种情况,因为它们具有不同的生命周期)。通常,除了在“业务方法”的上下文中之外,您不会在 EJB 中实例化任何东西,因此它的引用是短暂的。这也是因为您没有得到对 ejb 的具体引用,只有一个代理,它充当底层 bean 池的外观,其中任何一个都可以编组以在容器认为合适的情况下回答业务方法执行。
  • @Thomas,我没听错吧,您不使用 EE 服务器提供的数据源,而是在您的应用程序中创建一个池?
  • @user3714601 是的,您是正确的,因为我没有使用 EE 服务器提供的数据源。我正在使用 Hibernate/C3P0,但在我的应用程序中创建了一些应用程序托管的 EntityMangerFactories。我已经在这里问过这个问题:stackoverflow.com/questions/50755414/… 并没有比为每个用户创建一个 EntityMangerFactory 更好的主意。我预计最多 100 个用户,所以我想这仍然是可行的。如果你有更好的想法如何做到这一点,我很想听听。
【解决方案2】:

EJB 3.2 规范 (16.2.2) 明确指出:您不能这样做!

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

只需为您的单例使用常规字段并将创建移至@PostConstruct。 如果单例也是托管的,请在此字段上使用注入。

【讨论】:

    猜你喜欢
    • 2012-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-29
    • 2020-04-07
    • 2010-12-26
    • 2014-12-28
    相关资源
    最近更新 更多