Pergunta

More specifically, this is AjaxStateManager in Richfaces 3.1.HomeMadePatch/JSF1.1. I am not responsible for these technological choices, and I already read related questions like 1, 2, 3 which basically advice to upgrade versions or switch for a stateless JSF, which I would be very glad to do if I could, but due to the big hugeness of the application I am afraid I can't do this.

Back to the topic, I am currently trying to optimize memory heap consumption. Since my predecessors set a session scope for almost every bean, and set a server timeout of 6 hours (with some javascript refreshing before it expires in the browser), users have very long sessions and keep accumulating memory. I made some optimization on my own (well it is kind of simulating conversation scope: when hitting some pages, I clean everything in the main beans). Now when the users come back to main page their session wheights around 300kb, broken down as follow:

  • AjaxStateManager$SynchronizedStateHolder: 280kb
  • Other objects in session: 20kb

Those results were obtained by making heapdump and analyzing memory with Eclipse MAT. As you can see, 93% of the memory is Ajax maintening useless states. I want to force it to release those useless states. Any Idea on how to do this?

I thought about limiting the number of views it can save but in some pages there are some very weird form imbrications that I am unsure it would not break if I did.

Thanks in advance..

Foi útil?

Solução

Ok, so just in case, here is a relevant link about the problem, saying basically that there is no fix because it is inherent to the mechanisms of JSF. I resorted to using the parameter step on the number of views, which seems the more clean.

But I also experimented some dirty fixing. I am posting it there for future reference. Use at your own risk, because there is no guarantee.

package com.mycompany.ajaxutils;

import javax.faces.application.StateManager;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;

import org.ajax4jsf.application.AjaxStateManager;
import org.ajax4jsf.util.LRUMap;

public class AjaxStateHelper {
    private static final AjaxSateManagerUncover asmu = new AjaxSateManagerUncover(null);

    public static void cleanAjaxStateManager() {
        HttpSession currentSession = (HttpSession) FacesContext.getCurrentInstance().getExternalContext()
                .getSession(false);
        LRUMap lrumap = asmu.getLRUMap(currentSession.getAttribute(AjaxStateManager.class.getName()
                + ".VIEW_STATES_MAP"));
        lrumap.clear();
    }

    /**
     * This inner class is needed because we need to make a cast to a SynchronizedStateHolder
     * which is an inner protected class inside AjaxStateManager
     */
    protected static class AjaxSateManagerUncover extends AjaxStateManager {

        public AjaxSateManagerUncover(StateManager parent) {
            super(parent);
        }

        public LRUMap getLRUMap(Object stateMap) {
            SynchronizedStateHolder s = (SynchronizedStateHolder) stateMap;
            return s.getStateMap();
        }
    }
}

Just call AjaxStateHelper.cleanAjaxStateManager(); from wherever you need it in your application and it will free the memory for you. But beware the potential side effects, this is experimental code

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top