此问题特定于OmniFaces @ViewScoped bean(但是,使用JSF @ViewScoped进行有关内存泄漏和资源处理的更广泛讨论会引起您的兴趣)。它基于GitHub上此NetBeans8.1测试Web应用程序的结果:
Investigation of undesirable holding of references to various forms of JSF @ViewScoped beans by navigation type
https://github.com/webelcomau/JSFviewScopedNav
该测试Web应用程序具有全面的自述文件,其中包含完整的说明,以及带注释的测试Web页面,它们比较了过时的JSF2.0风格的@ManagedBean @ViewScoped
,JSF2.2风格的CDI友好的@Named @ViewScoped
和OmniFaces @Named @ViewScoped
bean。
使用JVisualVM进行诊断的结果总结在一个可下载的电子表格中(另请参见下面的屏幕快照),并表明,当OmniFaces-2.5.1 @ViewScoped
bean在离开视图时,在基于GET的导航情况下调用@PreDestroy方法(给出机会释放大部分资源),它似乎不允许对实际bean进行垃圾回收(至少不允许使用当前上下文参数设置)。
在web.xml中,该应用程序设置为使用:
com.sun.faces.numberOfViewsInSession 4
com.sun.faces.numberOfLogicalViews 4
默认情况下,此特定于OmniFaces的参数被注释掉:
org.omnifaces.VIEW_SCOPE_MANAGER_MAX_ACTIVE_VIEW_SCOPES
javax.faces.STATE_SAVING_METHOD默认为'server'。
主要问题是:
问题1:对这些OmniFaces
@ViewScoped
bean不能按设计的方式进行“实时”垃圾收集(这是通过使用Profiler的垃圾收集g动作进行挑衅,而不是等到会话结束)才是正确的吗?问题2:如果是这样,那么在离开页面时(尤其是在GET导航下),如何(应该)最好地释放它们?
问题3:如果不是这样(如果由于其他设置而导致我的结果不正确),为什么我没有目睹它们被激怒地进行垃圾收集,我该怎么做以确保确实将它们自动释放?
由于该测试Web应用程序是可下载的,有据可查的文档,并且希望能不言自明,因此,在此我将不提供代码,仅提供到目前为止的比较结果以及实际使用的测试Web应用程序页面的屏幕截图:
最佳答案
出现此问题的原因似乎是由于将JVisualVM连接到Glassfish / Payara时发生了奇怪的行为。
test case used for this question仍然非常有用,但是原始帖子(和图像)中有关垃圾收集的结论是基于JVisualVM的,此后我发现它们是无效的。
请改用NetBeans Profiler!
现在,通过从NetBeans Profiler内强制执行GC的测试应用程序,我获得OmniFaces ViewScoped的结果完全一致(每个打开的选项卡上都有1个omnifaces视图作用域的bean)。
当使用附加到GlassFish / Payara的JVisualVM时,即使在sessionListeners
中类型为com.sun.web.server.WebContainerListener
的字段ContainerBase$ContainerBackgroundProcessor
中,引用仍保持引用(即使在@PreDestroy调用之后),它们不会GC。
该图显示了连接到Payara的JVisualVM的屏幕截图,仅打开了1个选项卡,但仍然保留9个OmniViewBean实例,无论强制执行GC的频率如何。
在NetBeans IDE 8.2 Profiler中使用Mojarra-2.3.0和OmniFaces-2.6.6更新了结果表
更新的test app顺序: