此问题特定于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应用程序页面的屏幕截图:

jsf - JSF:Mojarra与OmniFaces @ViewScoped:@PreDestroy被调用,但无法对bean进行垃圾收集-LMLPHP

jsf - JSF:Mojarra与OmniFaces @ViewScoped:@PreDestroy被调用,但无法对bean进行垃圾收集-LMLPHP

jsf - JSF:Mojarra与OmniFaces @ViewScoped:@PreDestroy被调用,但无法对bean进行垃圾收集-LMLPHP

jsf - JSF:Mojarra与OmniFaces @ViewScoped:@PreDestroy被调用,但无法对bean进行垃圾收集-LMLPHP

jsf - JSF:Mojarra与OmniFaces @ViewScoped:@PreDestroy被调用,但无法对bean进行垃圾收集-LMLPHP

jsf - JSF:Mojarra与OmniFaces @ViewScoped:@PreDestroy被调用,但无法对bean进行垃圾收集-LMLPHP

最佳答案

出现此问题的原因似乎是由于将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的频率如何。

jsf - JSF:Mojarra与OmniFaces @ViewScoped:@PreDestroy被调用,但无法对bean进行垃圾收集-LMLPHP



在NetBeans IDE 8.2 Profiler中使用Mojarra-2.3.0和OmniFaces-2.6.6更新了结果表

jsf - JSF:Mojarra与OmniFaces @ViewScoped:@PreDestroy被调用,但无法对bean进行垃圾收集-LMLPHP

更新的test app顺序:

jsf - JSF:Mojarra与OmniFaces @ViewScoped:@PreDestroy被调用,但无法对bean进行垃圾收集-LMLPHP



jsf - JSF:Mojarra与OmniFaces @ViewScoped:@PreDestroy被调用,但无法对bean进行垃圾收集-LMLPHP



jsf - JSF:Mojarra与OmniFaces @ViewScoped:@PreDestroy被调用,但无法对bean进行垃圾收集-LMLPHP



jsf - JSF:Mojarra与OmniFaces @ViewScoped:@PreDestroy被调用,但无法对bean进行垃圾收集-LMLPHP

10-06 01:28