Como detectar e remover (durante uma sessão) beans @ViewScoped não utilizados que não podem ser coletados com lixo
EDIT: O problema levantado por esta pergunta é muito bem explicado e confirmado neste artigo por codebulb.ch, incluindo algumas comparações entre JSF@ViewScoped
, CDI@ViewSCoped
e os Omnifaces@ViewScoped
e uma declaração clara de que o JSF@ViewScoped
é "com vazamento por design":24 de maio de 2015 Os escopos do Java EE 7 Bean compararam a parte 2 de 2
EDIT: 2017-12-05 O caso de teste usado para esta pergunta ainda é extremamente útil, no entanto, as conclusões sobre a Coleta de Lixo na postagem original (e nas imagens) foram baseadas no JVisualVM e, desde então, constatamos que não são válidas.Use o NetBeans Profiler! Agora, estou obtendo resultados completamente consistentes para o OmniFaces ViewScoped com o aplicativo de teste para forçar o GC a partir do NetBeans Profiler em vez do JVisualVM anexado ao GlassFish / Payara, onde estou recebendo referências ainda mantidas (mesmo depois que o @PreDestroy chamado) por camposessionListeners
do tipocom.sun.web.server.WebContainerListener
dentroContainerBase$ContainerBackgroundProcessor
, e eles não vão GC.
Sabe-se que no JSF2.2, para uma página que usa um bean @ViewScoped, navegando para longe dele (ou recarregando-o) usando qualquer uma das técnicas a seguir resultará em instâncias do bean @ViewScoped "pendurado" na sessão para que não será coletado como lixo, levando a uma memória de pilha crescente sem fim (desde que provocada por GETs):
Usando um link h: para obter uma nova página.
Usando um h: outputLink (ou uma tag HTML A) para obter uma nova página.
Recarregando a página no navegador usando um comando ou botão RELOAD.
Recarregando a página usando um teclado ENTER no URL do navegador (também um GET).
Por outro lado, passar pelo sistema de navegação JSF usando o comando say an h: commandButton resulta na liberação do bean @ViewScoped para que ele possa ser coletado de lixo.
Isso é explicado (por BalusC) emO método JSF 2.1 ViewScopedBean @PreDestroy não é chamado e demonstrado para JSF2.2 e Mojarra 2.2.9 pelo meu pequeno projeto de exemplo do NetBeans emhttps://stackoverflow.com/a/30410401/679457, que projeto ilustra os vários casos de navegação e édisponível para download aqui. (EDIT: 2015-05-28: o código completo agora também está disponível aqui abaixo.)
[EDIT: 2016-11-13 Agora também há um aplicativo da Web de teste aprimorado com instruções completas e comparação com o OmniFaces@ViewScoped
e tabela de resultados no GitHub aqui:https://github.com/webelcomau/JSFviewScopedNav]
Repito aqui uma imagem do index.html, que resume os casos de navegação e os resultados da memória heap:
P: Como posso detectar esses grãos @ViewScoped "pendurados / pendurados" causados pelas navegações GET e removê-los ou torná-los coletáveis?
Observe que não estou perguntando como limpá-los quando a sessão terminar, já vi várias soluções para isso, estou procurando maneiras de limpá-los durante uma sessão, para que a memória da pilha não cresça excessivamente durante uma sessão devido a navegações GET inadvertidas.