High CPU in JSF ViewScopeManager.destroyBeans

Solution Unverified - Updated

Environment

  • JBoss Enterprise Application Platform 6.2.4 and earlier

Issue

  • We see high CPU in the ContainerBackgroundProcessor thread when it is calling ViewScopeManager.destroyBeans for a session expiration event:
 "ContainerBackgroundProcessor[StandardEngine[jboss.web]]" daemon prio=10 tid=0x00007ff12c02e800 nid=0x2a84 runnable [0x00007ff17922d000]
    java.lang.Thread.State: RUNNABLE
 	at java.util.concurrent.ConcurrentHashMap.hash(ConcurrentHashMap.java:333)
 	at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:988)
 	at com.sun.faces.mgbean.BeanManager.destroy(BeanManager.java:280)
 	at com.sun.faces.application.view.ViewScopeManager.destroyBeans(ViewScopeManager.java:139)
 	at com.sun.faces.application.view.ViewScopeManager.sessionDestroyed(ViewScopeManager.java:296)
 	at com.sun.faces.application.WebappLifecycleListener.sessionDestroyed(WebappLifecycleListener.java:171)
 	at com.sun.faces.config.ConfigureListener.sessionDestroyed(ConfigureListener.java:373)
 	at org.apache.catalina.session.StandardSession.expire(StandardSession.java:681)
 	- locked <0x0000000767c44f20> (a org.apache.catalina.session.StandardSession)
 	at org.apache.catalina.session.StandardSession.isValid(StandardSession.java:576)
 	at org.apache.catalina.session.ManagerBase.processExpires(ManagerBase.java:382)
 	at org.apache.catalina.session.ManagerBase.backgroundProcess(ManagerBase.java:367)
 	at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1302)
 	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1588)
 	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1600)
 	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1600)
 	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1574)
 	at java.lang.Thread.run(Thread.java:744)

Resolution

  • Upgrade to EAP 6.3.0 or later to acquire the fix from JSF 2.1.28
  • Another option that might workaround the issue without a JSF version change is a custom SessionListener class like the following:
package com.redhat.example
import com.sun.faces.application.view.ViewScopeManager;
import com.sun.faces.util.LRUMap;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
...
public class SessionListener implements HttpSessionListener {
    @Override
    public void sessionCreated(final HttpSessionEvent event) {
        final HttpSession session = event.getSession();
        session.setAttribute(ViewScopeManager.ACTIVE_VIEW_MAPS_SIZE, Integer.valueOf(25));
        session.setAttribute(ViewScopeManager.ACTIVE_VIEW_MAPS, Collections.synchronizedMap(new LRUMap(25)));
    }
...
}
  • You would configure that listener in your application's WEB-INF/web.xml:
<listener>
    <listener-class>com.redhat.example.SessionListener</listener-class>
</listener>

Root Cause

Components
Category

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.