Last Updated: February 25, 2016
·
1.313K
· stefanbirkner

Threads blocked at DefaultInstanceManager.preDestroy

Sometimes my Tomcat needs a lot of time for responses. When I look at the stack trace I see very much blocking threads:

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)

Looking deeper into the stack trace I see that this method is always called by the _jspDestroy method of a tag file's class, which calls org.apache.jasper.runtime.TagHandlerPool.release and so on. There are three solutions to avoid the problem.

Don't use tag files.

Avoid annotation scanning as long as you are not using Servlet 3.0 annotations to configure your webapp.

Therefore you only have to add another attribute to your web.xml's root node.

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

This sets the DefaultInstanceManager's ignoreAnnotations property to true and thereby prevents the execution of preDestroy.

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

Create a patch for Tomcat that fixes the problem.

I don't understand why the tag file always releases the TagHandlerPool. It is fetched by the tag file's _jspInit

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

and released at the end of its doTag(). This turns up to be a weird behaviour, which has negative effect on tag file performance. It should suffice to call TagHandlerPool.reuse on every tag that is fetched from the pool.

That's just the opinion of someone who doesn't know tag file code generation in details. Maybe I learn the origin of this behaviour in the next few days.