Uploaded image for project: 'MyFaces Core'
  1. MyFaces Core
  2. MYFACES-1658

Memory leak in JspStateManagerImpl

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 1.2.0
    • 1.2.0
    • General
    • None
    • JDK1.5, using Tomcat 5.5.

    Description

      We are working on a JSF project and recently started stress testing the system. This stress-testing caused the JVM to run out of memory and spend most of it time doing Full GC. Analyzing the heap revealed that most of the memory was being retained by SerializedViewCollection instances. We also noticed that the value of NUMBER_OF_VIEWS_IN_SESSION didn't seem to affect the memory usage.

      It seems the problem is due to the _oldSerializedViews hashmap which is supposed to use soft references and hence be GC-ed whenever there is a lack of memory, but this apparently doesn't work. Removing this hashmap completely solved the problem. It is however difficult to provide a simple testcase as we used JMeter to load the server with 600 users fetching a fairly big JSF page with a constant throughput of 20 requests per second.

      I should also mention that we found this problem with 1.1.4 but I fixed it with the 1.1.5 release.

      Here's the diff output:

      ~/code/myfaces-1.1.5/impl/src/main/java/org/apache/myfaces/application/jsp$ svn diff
      Index: JspStateManagerImpl.java
      ===================================================================
      — JspStateManagerImpl.java (revision 543859)
      +++ JspStateManagerImpl.java (working copy)
      @@ -18,7 +18,6 @@
      */
      package org.apache.myfaces.application.jsp;

      -import org.apache.commons.collections.map.ReferenceMap;
      import org.apache.commons.lang.builder.EqualsBuilder;
      import org.apache.commons.lang.builder.HashCodeBuilder;
      import org.apache.commons.logging.Log;
      @@ -609,10 +608,6 @@
      private final List _keys = new ArrayList(DEFAULT_NUMBER_OF_VIEWS_IN_SESSION);
      private final Map _serializedViews = new HashMap();

      • // old views will be hold as soft references which will be removed by
      • // the garbage collector if free memory is low
      • private transient Map _oldSerializedViews = null;
        -
        public synchronized void add(FacesContext context, Object state) {
        Object key = new SerializedViewKey(context);
        _serializedViews.put(key, state);
        @@ -623,10 +618,7 @@
        int views = getNumberOfViewsInSession(context);
        while (_keys.size() > views) {
        key = _keys.remove(0);
      • Object oldView = _serializedViews.remove(key);
      • if (oldView != null) { - getOldSerializedViewsMap().put(key, oldView); - }

        + _serializedViews.remove(key);
        }
        }

      @@ -660,23 +652,9 @@
      return views;
      }

      • /**
      • * @return old serialized views map
      • */
      • protected Map getOldSerializedViewsMap() {
      • if (_oldSerializedViews == null) { - _oldSerializedViews = new ReferenceMap(); - }
      • return _oldSerializedViews;
      • }
        -
        public Object get(Integer sequence, String viewId) {
        Object key = new SerializedViewKey(viewId, sequence);
      • Object value = _serializedViews.get(key);
      • if (value == null) { - value = getOldSerializedViewsMap().get(key); - }
      • return value;
        + return _serializedViews.get(key);
        }
        }

      Attachments

        Issue Links

          Activity

            People

              bruno_dev Bruno Aranda
              andre.naess@gmail.com André Næss
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: