每个会话的内存增长
我们使用JSF 2.2(2.2.12)与Mojarra时遇到了高内存消耗问题。经过对我们的负载测试进行调查,发现我们的ViewScoped Beans中的数据量相当大(有时超过1MB)。无论如何,在从视图导航到另一个视图时,会话内存大小不断增长。我们无法在短期内减少bean的大小,因此这种行为产生了相当大的影响。
解决方案1 - 更改上下文参数(不起作用)
现在,我们尝试使用官方Mojarra上下文参数(默认设置为15):
com.sun.faces.numberOfLogicalViews
com.sun.faces.numberOfViewsInSession
将这些参数降低并没有对我们的负载测试中的内存消耗产生任何影响。
解决方案2 - 更改activeViewMapsSize
(有效)
我们在调试Mojarra时发现了ViewScopeManager
中的以下代码:
Integer size = (Integer) sessionMap.get(ACTIVE_VIEW_MAPS_SIZE);
if (size == null) {
size = 25;
}
默认情况下,保留最后访问的视图大小似乎为25。看到这一点,我们实现了一个会话监听器,将该值设置为1:
public class SetActiveViewMapsSizeSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent event) {
event.getSession().setAttribute(ViewScopeManager.ACTIVE_VIEW_MAPS_SIZE, 1);
}
}
显然这很有效。由于只保留一个视图,内存不再增长。
那么为什么要在内存中保存25个视图?
因此,如果会话中未定义不同的值,则Mojarra会在内存中保留25个视图的历史记录。我找不到任何关于此的文档。有人能解释一下这是用于什么的吗?是用于浏览器返回吗?我们已经禁用了JSF页面上的缓存。因此,浏览器返回将始终创建一个新视图。这对我们来说不应该是问题。
解决方案2是否有效?有人能解释一下此方法的缺点吗?
更新1
经过各种评论和更深入的调试,结果显示:
com.sun.faces.numberOfLogicalViews
定义了 logicalViewMap 的大小,它仅(!)存储ui组件树的状态com.sun.faces.application.view.activeViewMapsSize
定义了 activeViewMap 的大小,它保存了 ViewScoped bean
将 numberOfLogicalViews
更改为 1 时,Mojarra 仍将跟踪最近 25 个视图的所有视图范围 bean。当你以另一种方式配置它-将 numberOfLogicalViews
设置为 15,activeViewMapsSize
设置为 1 时-由于缺少数据,视图无法正确初始化,我猜。我们甚至没有得到异常。我想了解为什么 Mojarra 选择将 activeViewMapsSize
设置为比 numberOfLogicalViews
更高而不是相同的,因为我们想调整内存消耗而不会出现不可预测的行为。
更新2
我们在Mojarra上创建了一个问题:JAVASERVERFACES-4015。
com.sun.faces.application.view.activeViewMapsSize
(ACTIVE_VIEW_MAPS_SIZE值后面的)这样的WebContextInitParameter。让我想知道的是数值25!为什么这么多。 - fischermattenumberOfLogicalViews
。这个解决方法是很好的。另一个选择是切换到 OmniFaces 的@ViewScoped
,它会遵循numberOfLogicalViews
。 - BalusCnumberOfLogicalViews * numberOfViewsInSession
相同,但是现在numberOfViewsInSession
很少有用。至少,每个视图状态都应该附有一个视图作用域的 bean,并且当关联的视图状态被移除时不应该有悬空的视图作用域 bean。 - BalusC@ViewScoped
将在页面卸载时立即销毁,因此不会再无必要地停留在会话中。 - BalusC