gpt4 book ai didi

java - JMX:如何防止 servlet 容器中的类加载器内存泄漏?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:00:50 25 4
gpt4 key购买 nike

我想知道我是否应该或如何处理直接或间接从部署在 servlet 容器上的应用程序注册的 MBean。

在大多数情况下,有两个选项可以检索可用于注册的 MBeanServer

  • 使用 MBeanServerFactory.createMBeanServer()

    创建您自己的 MBeanServer
  • 使用ManagementFactory.getPlatformMBeanServer()

使用第一个选项时,很容易注销所有 MBean:只需调用 MBeanServer.releaseMBeanServer(myMBeanServer)

但是在许多第 3 方应用程序中经常使用的第二个选项呢?(顺便说一句,这也是 Sun/Oracle 推荐的方式)。

因为使用了平台 MBeanServer,所以当 servlet 上下文被销毁时它不会被注销 - 但更糟糕的是它仍然持有对 Web 应用程序类加载器的引用。
因此,Web 应用程序的所有静态引用都不会被释放,从而导致泄漏。

如果您想对此进行测试:只需部署一个简单的 Web 应用程序,该应用程序分配一个 100MB 的数组,该数组是静态引用并使用 oracle jdbc 驱动程序(它将使用平台 mbean 服务器注册诊断 MBean),部署在 tomcat 上。停止应用程序并重新启动它 - 重复此操作,您将遇到 OutOfMemoryError

问题:

  • 我需要处理这些问题吗?还是 servlet 容器和/或第 3 方库的问题?

  • 有没有办法获取 MBeanServer 的所有 MBean,哪些类由特定的 ClassLoader 加载?

  • 我该怎么做才能防止这种情况发生?我是否必须跟踪所有注册到平台 MBeanServer 的 MBean 并在 contextDestroyed() 期间注销它?

最佳答案

我正在使用如此邪恶的第三方。为确保正确关闭 servlet 上下文,我使用 mbeanServer.queryMBeans(null, null) 枚举 bean,然后使用 unregisterMBean() 枚举位于第三个域中的 bean-派对。

Set<ObjectInstance> beans = mbeanServer.queryMBeans(null, null);
for (ObjectInstance objectInstance : beans) {
if (objectInstance.getObjectName().getDomain().equals("third-party-domain")) {
try {
mbeanServer.unregisterMBean(objectInstance.getObjectName());
} catch (MBeanRegistrationException exception) {
//error handling
} catch (InstanceNotFoundException exception) {
//error handling
}
}
}

关于java - JMX:如何防止 servlet 容器中的类加载器内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6415831/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com