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@ViewSCopede os Omnifaces@ViewScopede 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.

questionAnswers(2)

yourAnswerToTheQuestion