JSF应用内存占用过高问题排查及优化方案咨询
问题背景相关截图
问题解答
- JSF占用如此高的内存是否正常?如何降低内存占用?
该内存占用水平明显不正常,正常业务场景下单个JSF视图内存占用通常在几百KB到3MB区间,单视图达到23MB属于严重异常。
降低内存占用的可行方案:
- 优先排查单个视图的组件树是否持有了大量不必要的业务数据,比如大体积的查询结果集、文件字节流、冗余业务对象等直接绑定到组件属性的情况
- 开启JSF部分状态保存机制,只保存变更的组件状态而非全量组件树,配置参数为
com.sun.faces.partialStateSaving=true - 清理视图中未使用的冗余组件、隐藏组件,避免无效对象长期驻留
大量使用自定义标签及其中的EL条件表达式,是否会引发该问题?
确实有可能。
如果自定义标签没有正确重写release()方法,会导致每次标签渲染产生的属性对象、临时对象无法被回收,长期累积就会导致内存暴涨。另外EL表达式如果直接绑定大对象、或者每次求值时都会生成新的临时对象没有被及时回收,也会加剧内存占用问题。将活跃视图数量降至最低是否是合理方案?已调整com.sun.faces.numberOfLogicalViews和com.sun.faces.numberOfViewsInSession从15到6
这个方向是合理的,属于有效缓解内存压力的手段,但属于治标方案。
参数下调后可以直接降低每个会话持有的视图总内存,但如果单视图本身23MB的内存超标问题没有解决,即便继续下调参数,仍然会存在内存占用过高的问题,还可能引发用户多开页面时视图过期的报错。建议配合缩短非活跃会话的超时时间,及时销毁闲置会话释放内存。ViewScoped Bean的正确使用方式是什么?承载数据表查询结果是否合理,还是应该使用RequestScoped?
ViewScoped Bean的生命周期和当前用户的页面视图绑定,只要用户不关闭、不跳转当前页面,Bean就会一直驻留在内存中。
如果是需要跨多次请求复用的小数据量分页查询结果,用ViewScoped是合理的;如果是单次查询就用完的全量大数据集、或者不需要跨请求保留的查询结果,优先用RequestScoped,请求结束后Bean会直接被GC回收,不会长期占用内存。大部分普通业务的数据表查询场景都更推荐用RequestScoped,配合每次请求加载当前页数据即可,不需要把全量结果都存在视图里。
内容的提问来源于stack exchange,提问作者dssof



