JSF:Mojarra 与 OmniFaces @ViewScoped:@PreDestroy 已调用但 bean 不能被垃圾收集
JSF: Mojarra vs. OmniFaces @ViewScoped: @PreDestroy called but bean can't be garbage collected
这个问题是 OmniFaces @ViewScoped bean 特有的(但是,关于 JSF @ViewScoped 的内存泄漏和资源处置的更广泛讨论很有趣)。它基于 GitHub:
上可用的 NetBeans8.1 测试 Web 应用程序的结果
https://github.com/webelcomau/JSFviewScopedNav
该测试 Web 应用程序具有包含完整说明的综合自述文件,以及比较过时的 JSF2.0 样式 @ManagedBean @ViewScoped
、JSF2.2 样式 CDI-friendly [=13 的带注释的测试网页=],和 OmniFaces @Named @ViewScoped
个豆子。
使用 JVisualVM 进行诊断的结果总结在一个可下载的电子表格中(另请参见下面的屏幕截图),并表明当 OmniFaces-2.5.1 @ViewScoped
bean 在 GET-based 下调用 @PreDestroy 方法时离开视图时的导航情况(提供释放大部分资源的机会),它似乎不允许对实际 bean 进行垃圾收集(至少不允许使用当前的上下文参数设置)。
在 web.xml 中,应用程序设置为使用:
com.sun.faces.numberOfViewsInSession 4
com.sun.faces.numberOfLogicalViews 4
默认这个OmniFaces-specific参数被注释掉:
org.omnifaces.VIEW_SCOPE_MANAGER_MAX_ACTIVE_VIEW_SCOPES
javax.faces.STATE_SAVING_METHOD默认为'server'。
主要问题是:
Q1:这些 OmniFaces @ViewScoped
beans 不能通过设计被垃圾收集 "live" 是否正确(意思是通过使用 Profiler 的垃圾收集操作来激发,而不是等到会话结束结束)?
Q2:如果是这样,如何(应该)在离开页面(尤其是在 GET 导航下)时强制释放它们?
问题 3:如果不是这样(如果我的结果由于某些其他设置不正确)为什么我没有看到它们被激发的垃圾收集,我该怎么做才能确保它们确实被自动释放?
由于测试网络应用程序是可下载的,有据可查,希望 self-explanatory,我不会在这里给出代码,而只是到目前为止的比较结果,以及测试网络应用程序页面的屏幕截图动作:
这个问题的原因似乎是 JVisualVM 附加到 Glassfish/Payara 时的奇怪行为。
test case used for this question 仍然非常有用,但是原始 post(和图像)中关于垃圾收集的结论是基于 JVisualVM 的,后来我发现它们是无效的。
改用 NetBeans Profiler!
我现在在 OmniFaces ViewScoped 上获得完全一致的结果,测试应用程序在 NetBeans Profiler 中强制执行 GC(每个打开的选项卡留下 1 个 omnifaces 视图作用域 bean)。
当使用附加到 GlassFish/Payara 的 JVisualVM 时,我得到的引用仍然由 ContainerBase$ContainerBackgroundProcessor
中类型 com.sun.web.server.WebContainerListener
的字段 sessionListeners
保留(即使在调用 @PreDestroy 之后),并且他们不会 GC。
该图显示了附加到 Payara 的 JVisualVM 的屏幕截图,其中仅打开了 1 个选项卡,但仍然保留了 9 个 OmniViewBean 实例,无论强制执行 GC 的频率如何。
更新结果table 在 NetBeans IDE 8.2 Profiler
中使用 Mojarra-2.3.0 与 OmniFaces-2.6.6
已更新 test app 序列:
这个问题是 OmniFaces @ViewScoped bean 特有的(但是,关于 JSF @ViewScoped 的内存泄漏和资源处置的更广泛讨论很有趣)。它基于 GitHub:
上可用的 NetBeans8.1 测试 Web 应用程序的结果https://github.com/webelcomau/JSFviewScopedNav
该测试 Web 应用程序具有包含完整说明的综合自述文件,以及比较过时的 JSF2.0 样式 @ManagedBean @ViewScoped
、JSF2.2 样式 CDI-friendly [=13 的带注释的测试网页=],和 OmniFaces @Named @ViewScoped
个豆子。
使用 JVisualVM 进行诊断的结果总结在一个可下载的电子表格中(另请参见下面的屏幕截图),并表明当 OmniFaces-2.5.1 @ViewScoped
bean 在 GET-based 下调用 @PreDestroy 方法时离开视图时的导航情况(提供释放大部分资源的机会),它似乎不允许对实际 bean 进行垃圾收集(至少不允许使用当前的上下文参数设置)。
在 web.xml 中,应用程序设置为使用:
com.sun.faces.numberOfViewsInSession 4
com.sun.faces.numberOfLogicalViews 4
默认这个OmniFaces-specific参数被注释掉:
org.omnifaces.VIEW_SCOPE_MANAGER_MAX_ACTIVE_VIEW_SCOPES
javax.faces.STATE_SAVING_METHOD默认为'server'。
主要问题是:
Q1:这些 OmniFaces @ViewScoped
beans 不能通过设计被垃圾收集 "live" 是否正确(意思是通过使用 Profiler 的垃圾收集操作来激发,而不是等到会话结束结束)?
Q2:如果是这样,如何(应该)在离开页面(尤其是在 GET 导航下)时强制释放它们?
问题 3:如果不是这样(如果我的结果由于某些其他设置不正确)为什么我没有看到它们被激发的垃圾收集,我该怎么做才能确保它们确实被自动释放?
由于测试网络应用程序是可下载的,有据可查,希望 self-explanatory,我不会在这里给出代码,而只是到目前为止的比较结果,以及测试网络应用程序页面的屏幕截图动作:
这个问题的原因似乎是 JVisualVM 附加到 Glassfish/Payara 时的奇怪行为。
test case used for this question 仍然非常有用,但是原始 post(和图像)中关于垃圾收集的结论是基于 JVisualVM 的,后来我发现它们是无效的。
改用 NetBeans Profiler!
我现在在 OmniFaces ViewScoped 上获得完全一致的结果,测试应用程序在 NetBeans Profiler 中强制执行 GC(每个打开的选项卡留下 1 个 omnifaces 视图作用域 bean)。
当使用附加到 GlassFish/Payara 的 JVisualVM 时,我得到的引用仍然由 ContainerBase$ContainerBackgroundProcessor
中类型 com.sun.web.server.WebContainerListener
的字段 sessionListeners
保留(即使在调用 @PreDestroy 之后),并且他们不会 GC。
该图显示了附加到 Payara 的 JVisualVM 的屏幕截图,其中仅打开了 1 个选项卡,但仍然保留了 9 个 OmniViewBean 实例,无论强制执行 GC 的频率如何。
更新结果table 在 NetBeans IDE 8.2 Profiler
中使用 Mojarra-2.3.0 与 OmniFaces-2.6.6已更新 test app 序列: