Threads bloqueados em DefaultInstanceManager.preDestroy

Às vezes, meu Tomcat precisa de muito tempo para respostas. Quando eu olho para o rastreamento de pilha, vejo muitos segmentos de bloqueio:

java.lang.Thread.State: BLOCKED (on object monitor)
at org
.apache.catalina.core.DefaultInstanceManager.preDestroy(DefaultInstanceManager.java:239)
- waiting to lock <0x00000007604daa80> (a java.util.WeakHashMap)

Olhando mais profundamente no rastreamento de pilha, vejo que esse método é sempre chamado pelo método _jspDestroy da classe de um arquivo de tag, que chama org.apache.jasper.runtime.TagHandlerPool.release e assim por diante. Existem três soluções para evitar o problema.

Não use arquivos de tag.

Evite a verificação de anotações , desde que você não esteja usando anotações do Servlet 3.0 para configurar seu webapp.

Portanto, você só precisa adicionar outro atributo ao nó raiz do web.xml.

<web-app metadata-complete="true"…

Isso define a propriedade ignoreAnnotations de DefaultInstanceManager como true e, portanto, evita a execução de preDestroy.

public void destroyInstance(Object instance)  {
if (!ignoreAnnotations) {
preDestroy
(instance, instance.getClass());
}
}

Crie um patch para o Tomcat que corrige o problema.

Não entendo por que o arquivo de tag sempre libera o TagHandlerPool. Ele é obtido pelo _jspInit do arquivo de tag

private void _jspInit(ServletConfig config) {
pool
= TagHandlerPool.getTagHandlerPool(config);

e lançado no final de sua doTag (). Isso acaba sendo um comportamento estranho, que tem efeito negativo no desempenho do arquivo de tag. Deve ser suficiente chamar TagHandlerPool.reuse em cada tag que é buscada no pool.

Essa é apenas a opinião de alguém que não conhece em detalhes a geração de código de arquivo de tag. Talvez eu descubra a origem desse comportamento nos próximos dias.