Связанные bean-компоненты ViewScoped приводят к утечкам памяти

В нашем проекте JavaEE6 (EJB3, JSF2) на JBoss 7.1.1 кажется, что у нас есть утечка памяти с bean-компонентами @ViewScoped. Последние три дня я потратил время на изучение этого вопроса. Поэтому я создал простой проект с двумя страницами, чтобы гарантировать, что после выхода первой страницы bean-компонент @ViewScoped будет выпущен.

<context-param>  //web.xml
   <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
   <param-value>server</param-value>
</context-param>
<context-param>
   <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
   <param-value>false</param-value>
</context-param>

TreeBean.java

@ManagedBean
@ViewScoped
public class TreeBean implements Serializable {
 private TreeNode root;  
 public static AtomicInteger count = new AtomicInteger(0);

@Override
protected void finalize() throws Throwable {
    System.out.println("TreeBean beans count: " + count.decrementAndGet() + " (FINALISATION)");
}


public TreeBean() {  
    super();
    System.out.println("TreeBean beans count: " + count.incrementAndGet() + " (INITIALISATION)");
}  

первый.xhtml

  ....
  <h:form id="frm">
        <p:tree
            value="#{treeBean.root}"
            var="node"
            id="tree">
    ....
   <p:commandLink
            action="second.xhtml?faces-redirect=true"
            value="toSecond" />
    ....            

второй.xhtml

  ....
  <h:form id="frm">
    ....
   <p:commandLink
            action="first.xhtml?faces-redirect=true"
            value="toFirst" />
    ....

системный выход:

  INFO  [stdout] (http--0.0.0.0-8080-4) TreeBean beans count: 1 (INITIALISATION)
  INFO  [stdout] (http--0.0.0.0-8080-4) TreeBean beans count: 2 (INITIALISATION)
  INFO  [stdout] (http--0.0.0.0-8080-4) TreeBean beans count: 3 (INITIALISATION)
  ......
  INFO  [stdout] (Finalizer) TreeBean beans count: 2 (FINALISATION)
  INFO  [stdout] (Finalizer) TreeBean beans count: 1 (FINALISATION)
  INFO  [stdout] (Finalizer) TreeBean beans count: 0 (FINALISATION)

и все мысли шли хорошо, пока я не добавил зависимость к другому bean-компоненту @ViewScoped

TreeBean.java

@ManagedBean
@ViewScoped
public class TreeBean implements Serializable {
 private TreeNode root;  

@ManagedProperty(value = "#{treeNodeBean}")
private TreeNodeBean treeNodeBean;


 public static AtomicInteger count = new AtomicInteger(0);

@Override
protected void finalize() throws Throwable {
    System.out.println("TreeBean beans count: " + count.decrementAndGet() + " (FINALISATION)");
}


public TreeBean() {  
    super();
    System.out.println("TreeBean beans count: " + count.incrementAndGet() + " (INITIALISATION)");
}  

TreeNodeBean.java

@ManagedBean
@ViewScoped
public class TreeNodeBean implements Serializable {

     private String treeNodeItem="TreeNodeItem";

}

И после этого ни один бин не был выпущен. Кто-нибудь знает, как с этим бороться? Это баг или это где-то настраивается?


person bohdanius    schedule 26.10.2012    source источник
comment
Обратитесь к этой ссылке. Обход выполнен для JSf 2.1 и 2.2 /12182844/   -  person Sathish Kumar    schedule 03.02.2014


Ответы (1)


К сожалению, вы правы. Существуют известные проблемы с @ViewScoped управлением памятью (и они не связаны только с цепочкой представлений), как вы увидите здесь и здесь. Также посмотрите на этот вопрос. Вы можете поэкспериментировать с объектом UIViewRoot за текущий сеанс и вызвать getViewMap().remove("myView"). на основе какого-то события. Вы также можете попробовать это

Независимо от этого, почему вы связываете bean-компоненты с областью видимости? Они предназначены для использования как именованные для представлений. Вы ограничены в использовании SessionScoped?

person kolossus    schedule 27.10.2012
comment
Хотя vievscoped предназначен для более коротких периодов активности пользователя. Итак, bean работает, пока вы не покинете текущую страницу. Sessionscoped живет дольше, пока веб-сессия не прервется. Так что мой выбор был сохранить память. - person bohdanius; 27.10.2012
comment
@bohdanius, я полагаю, что в любом случае у вас уже есть компонент с областью действия сеанса в вашем веб-приложении, и если вы это сделаете, все, что вы храните в области представления, на которое вам нужно ссылаться в трех отдельных представлениях, должно храниться там. Затем вы можете взять на себя его очистку (установив для переменных значение null или что-то еще) или уничтожив его вместе с сеансом. Если у вас не установлен сессионный компонент, это веский аргумент в его пользу. Другой альтернативой является флеш-прицел, который применим в основном, если три вида являются последовательными. - person kolossus; 27.10.2012