ClassLoader leaks on JavaForum

0

Tonight I have talked about ClassLoader leaks on JavaForum Gothenburg. Below you will find the slides from the presentation, the link to the Leak prevention library on GitHub and links to all the parts of the blog series I made on the subject.

Video

Slides


Heinz Kabutz Java Specialists’ Newsletter The Law Of The Blind Spot referenced on slide 26.
Tomcat Bugzilla entries #48895 and #49159 referenced on slide 41.

Leak prevention library

GitHub project

Links to all parts in blog series

Part I – How to find classloader leaks with Eclipse Memory Analyser (MAT)

Part II – Find and work around unwanted references

Part III – “Die Thread, die!”

Part IV – ThreadLocal dangers and why ThreadGlobal may have been a more appropriate name

Part V – Common mistakes and Known offenders

Part VI – “This means war!” (leak prevention library)

Better compareTo() syntax

0

I’ve never really been a big fan of the syntax of java.lang.Comparable.compareTo(). For some reason I find myself constantly referring to the JavaDocs to remind me whether < 0 or > 0 means the argument is less vs more than the callee.

So I decided to do something about it, and created a minimal API with the sole purpose of improving readability of compareTo().

The API supplies methods in two flavors, expressive or abbreviated. The expressive version looks like this:

import static se.jiderhamn.CompareTo.is;

...
  boolean oneIsZero = is(1).equalTo(0);
  boolean aIsNotZero = is(a).notEqualTo(0);
  boolean bIsZero = is(b).zero();
  boolean value1LessThanValue2 = is(value1).lessThan(value2);
    
  if(is(a).lessThanOrEqualTo(b)) {
    ...
  }

  boolean date1AfterDate2 = is(date1).greaterThan(date2);

  if(is(a).greaterThanOrEqualTo(b)) {
    ...
  }

 

The abbreviated syntax looks like this:

import static se.jiderhamn.CompareTo.is;

...
  boolean oneIsZero = is(1).eq(0);
  boolean aIsNotZero = is(a).ne(0);
  boolean value1LessThanValue2 = is(value1).lt(value2);

  if(is(a).le(b)) {
    ...
  }

  boolean date1AfterDate2 = is(date1).gt(date2);

  if(is(a).ge(b)) {
    ...
  }

 

The API is available on Maven Central:

    <dependency>
      <groupId>se.jiderhamn</groupId>
      <artifactId>compare-to</artifactId>
      <version>1.1.1</version>
    </dependency>

Source are on GitHub.

Manual download here.

Debugging third party libraries with AspectJ and Maven

4

Once in a while you may find yourself in a situation, where you need to debug a third party library on a production server or other environment where it is not possible or impractical to attach a debugger. It may also be the case that modifying the sources of that library and compiling a custom version is not an option (due to compilation dependencies, licenses, source not available or whatnot).

I found myself in such a situation a while back when I needed to understand memory leaks in OpenOffice JURT. I achieved this by injecting debug logging into the library with AspectJ, and in this post I will describe how.

In my situation the third party library was a transitive Maven dependency. In order to weave this library with my own aspects, I added this to the pom.xml:

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <version>1.4</version>
        <configuration>
          <!-- Weave third party dependency -->
          <weaveDependencies>
            <weaveDependency>
              <groupId>org.openoffice</groupId>
              <artifactId>jurt</artifactId>
            </weaveDependency>
          </weaveDependencies>
        </configuration>
        <!-- Weave on compile -->
        <executions>
          <execution>
            <id>compile</id>
            <goals>
              <goal>compile</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

Note! In order for the weaved version of the library to be included in your .war, the above should be located in the web module if your Maven project has multiple modules. If your aspect is in another module you also need to add

          <aspectLibraries>
            <aspectLibrary>
              <groupId>your.project</groupId>
              <artifactId>module-with-aspect</artifactId>
            </aspectLibrary>
          </aspectLibraries>

to the configuration.

You’ll likely also want to add the AspectJ runtime dependency, for the aspect implementation.

    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.6.12</version>
    </dependency>

Now lets move on with the actual aspect. If you need an introduction to AspectJ, you may find this post useful. First we have our aspect class:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * AspectJ aspect used for debugging memory leaks caused by OpenOffice JURT
 * @author Mattias Jiderhamn
 */
@Aspect
public class JURTDebugAspect {
  
  private static final Logger LOG = LoggerFactory.getLogger(JURTDebugAspect.class);

  /** Utility method to get StackTraceElement of caller */
  private static StackTraceElement getCaller(int levels) {
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    return stackTrace[levels + 1];
  }

}

Inside that aspect class, we can add different joinpoints and advice to inject logging.

  @Before("execution(* com.sun.star.lib.util.AsynchronousFinalizer.add(..))")
  public void addCalled() {
    LOG.warn("JURT: add() called by " + getCaller(3));
  }

This will log calls to the third party API add() method, including calls from other third party libraries. Note that “execution” pointcut is used rather than “call” pointcut, since we are weaving the callee, not the caller. The getCaller() utility method also allows us to see what code called the add() method.

  @Before("call(* java.lang.Thread.start(..)) && within(com.sun.star.lib.util.*) && target(thread)")
  public void threadStarted(Thread thread) {
    LOG.warn("JURT: Thread.start() called by " + getCaller(2) + " on thread named " + 
      thread.getName() + " of type " + thread.getClass().getName());
  }

Here we add some logging for when the third party library calls the start() method on java.lang.Thread, and include the name and type of the started thread.

  @Around("call(* com.sun.star.lib.util.AsynchronousFinalizer$Job.run(..)) && within(com.sun.star.lib.util.*) && target(job)")
  public Object jobRun(ProceedingJoinPoint proceedingJoinPoint, Object job) throws Throwable {
    LOG.info("JURT: Job.run() starting: " + job.getClass().getName() + " in thread " +
      Thread.currentThread().getName());
    final long start = System.currentTimeMillis();
    try {
      return proceedingJoinPoint.proceed();
    }
    finally {
      LOG.info("JURT: Job.run() done: " + job.getClass().getName() + " in thread " +
        Thread.currentThread().getName() + "; took " + 
        (System.currentTimeMillis() - start) + " ms");
    }
  }

Here we log internal calls to Job.run() inside the API, and measure the time that those calls take. The name of the Job subclass is included.

Good luck debugging third party libraries!

Agile code review at nForum – video

0

When I talked about agile code review on nForum the other day, I made a screencast recording, which is now online. (I admit sound quality could have been somewhat better.)

For better readability of the slides, I recommend viewing the video in HD on Vimeo

Note that the slides and links to code review tools and further reading are in my previous post.

If you want to share the video, please link to this post rather than directly to Vimeo.

Agile code review at nForum

1

Tonight I’ve given a talk at nForum Göteborg on code review and how it can be used by agile teams. It was pretty much the same talk I gave at JavaForum a while back. I tried to make a recording of it, and will post a video and update this post, if successful.

Here are the (Swedish) slides:


Here are links to some code review tools:

In addition to this list, code review is one of the features of GitHub. In my opinion it has the same problems as e-mail based review, where it is hard to track what has been fixed and not.

Some reading suggestions on code review:
Coding Horror blog entry
Free book from the authors of Code Collaborator
White paper from the authors of Klocwork

Aspect-Oriented Programming (AOP) with AspectJ – an introduction

0

Tonight I have delievered a talk at JavaForum Gothenburg about Aspect-Oriented Programming (AOP) in general and AspectJ in particular.

Here are the slides of the presentation:

You will find the source code of the demos, including pom.xml to configure Maven for AspectJ weaving, on my GitHub account: https://github.com/mjiderhamn/aspectj-intro.

I intended to record the session as a screencast, but unfortunately my IDE decided freak out when I started coding some examples, so I had to restart it and decided to trash the recording in order to save time. There was a video camera present during the evening however, so maybe a video will turn up on the net at some time. I will however be grateful if the couple of minutes with crashing IDE is edited…

Classloader leaks VI – “This means war!” (leak prevention library)

30

This post is intended to conclude the series about classloader leaks, and I want to use it to declare war! (Not as in Web application archive though…)

I have decided to pursue the fight against classloader leaks, and I invite you to join me. For this purpose I have created a project on GitHub called classloader-leak-prevention. The project consists of two parts.

Classloader leak protection listener

First and foremost there is a component for you to add to your web application, that intends to remove and work around as many of the known issues as possible. This will allow us not to depend on bugs being fixed in third party libraries. Yes, this is somewhat like what Tomcat has built in, but my component covers cases that Tomcat currently does not. Another major advantage is that my component is Application Server independent.

It should be as easy as adding a JAR or .java file, configuring a ServletContextListener in web.xml, and you should be protected against java.lang.OutOfMemoryError: PermGen space caused by your app leaking classloaders (you could still run out of PermGen however, or other apps on the same server may leak). In due time, I hope that parts of it will be configurable to your needs (check back here for updates). If it is not configurable enough, feel free to subclass or create your own GitHub fork.

To configure the main prevention mechanism, just add the component to your project and insert this into your web.xml:

<listener>
  <listener-class>
    se.jiderhamn.classloader.leak.prevention.ClassLoaderLeakPreventor
  </listener-class>
</listener>

It makes sense to keep this listener “outermost” (initializing first, destroying last), so you should normally declare it before any other listeners in web.xml.

Maven

The library is available in Maven Central with the following details:

<dependency>
  <groupId>se.jiderhamn</groupId>
  <artifactId>classloader-leak-prevention</artifactId>
  <version>1.10.0</version>
</dependency>

Download

Non-Maven users can download the JAR with the current version (1.10.0) of the project » here «.

Configuration

The context listener has a number of settings, see the readme on GitHub.

Classloader leak detection / test framework

Another part of the project, is a framework that allows the creation of JUnit tests, that confirms classloader leaks in third party APIs. It is also possible to test leak prevention mechanisms to confirm that the leak really is avoided.

Read more about this on GitHub.

License

This project is licensed under the Apache 2 license, which allows you to include modified versions of the code in your distributed software, without having to release your source code.

Links to all parts in the series

Part I - How to find classloader leaks with Eclipse Memory Analyser (MAT)

Part II - Find and work around unwanted references

Part III - "Die Thread, die!"

Part IV – ThreadLocal dangers and why ThreadGlobal may have been a more appropriate name

Part V - Common mistakes and Known offenders

Part VI - "This means war!" (leak prevention library)

Presentation on Classloader leaks (video and slides)

Classloader leaks V – Common mistakes and Known offenders

4

A couple of years ago, there was an article on the Confluence site of the Spring framework written by Magnus Alvestad, titled “Memory leaks where the classloader cannot be garbage
collected” (originally located here/here). Apart from a short description of the problem with classloader leaks, it also contained a list of known offenders; practices and third party libraries known to cause classloader leaks, either by incorrect use or as a bug.

Even though not by far exhaustive, an article like that was a good reference – a place to start looking if you experienced java.lang.OutOfMemoryError: PermGen space. Unfortunately it seems that page is not available any more. My hope for this post is that it may serve that purpose instead. For that to come true, I also need your help. If you know of a public Java library that does, in a current or previous version, cause classloader leaks, please comment on this post. I intend to keep the list updated. (Please note that this is not an invitation for support requests, asking me whether a particular library does leak. I want you to report leaks that are confirmed, either by yourself or that there is an online bug report / mailing list discussion. References are preferrable!)

Common mistakes

Let’s start with the leaks that aren’t necessarily bugs, but failure to follow guidelines or best practice. It may also be API:s that have the potential to cause classloader leaks, while they also provide a means to avoid them.

Uncleared ThreadLocals

As we talked about in the previous post, you should always call remove() on a ThreadLocal in a finally block.

Unstopped threads

In part III of this series we talked about the importance of making sure threads started within your web app stop executing when the application is redeployed.

JDBC driver included in WAR

Your JDBC driver will be registered in java.sql.DriverManager, which means that if you include your JDBC driver inside your web application, there will be a reference to your webapps classloader from system classes (see part II). The simple solution is to put JDBC driver on server level instead, but you can also deregister the driver at application shutdown.

Logging frameworks

Logging frameworks such as Apache Commons Logging (ACL) – formerly Jakarta Commons Logging (JCL) – log4j and java.util.logging (JUL) will cause classloader leaks under some circumstances.

Apache Commons Logging will cause trouble if the logging framework is supplied outside of the web application, such as within the Application Server. In such a case, you need to add a bit of cleanup code to the ServletContextListener we’ve talked about:

org.apache.commons.logging.LogFactory.release(
  Thread.currentThread().getContextClassLoader());

or

org.apache.commons.logging.LogFactory.release(this.getClass().getClassLoader());

There is an article about this on the Apache Commons Wiki. It is also mentioned in the guide and FAQ.

When it comes to log4j, you can achieve the same kind of leak with some configurations. I’m not sure if calling org.apache.log4j.LogManager.shutdown() in the cleanup ServletContextListener helps, but it’s probably a good idea anyway, at least if there is only a single web application running on the server.

As for java.util.logging, it will always be outside the web application, since it is part of the JDK. With it you can cause classloader leaks by creating custom log Levels inside your web app. This is what Frank Kieviet uses as example in his blog post on classloader leaks.

There is also a thorough article about the problem with logging frameworks and classloaders here. As a general recommendation, SLF4J supposedly helps preventing at least some of these problems.

Bean instrospection

The Java Bean introspection has a cache with strong references, that need to be cleared by calling

java.beans.Introspector.flushCaches();

in the cleanup ServletContextListener. If you don’t want to create your own, you can use org.springframework.web.util.IntrospectorCleanupListener from the Spring framework.

Custom property editor

If a property editor loaded within the web application (or a property editor for a class loaded in the web application) is registered by calling java.beans.PropertyEditorManager.registerEditor() it needs to be deregistered at application shutdown, or it will cause classloader leaks. Deregistering can be achieved by calling java.beans.PropertyEditorManager.registerEditor() again with the same targetType but null as the second argument (editorClass).

Custom default java.net.Authenticator

Custom java.net.Authenticator loaded in your web application and registered with java.net.Authenticator.setDefault() must be unregistered at application shutdown, or it will cause leaks.

Custom default java.net.ProxySelector

Custom java.net.ProxySelector loaded in your web application and registered with java.net.ProxySelector.setDefault() must be unregistered at application shutdown, or it will cause leaks.

Custom java.security.Provider

Custom java.security.Provider loaded in your web application and registered with java.security.Security.addProvider() must be unregistered with java.security.Security.removeProvider() at application shutdown, or it will cause leaks.

Custom MBean

Custom MBeans registered in the MBeanServer (ManagementFactory.getPlatformMBeanServer().registerMBean()) needs to be unregistered at application shutdown, or they will cause leaks.

Undestroyed custom ThreadGroup

ThreadGroups are in a hierarchy with the “system” ThreadGroup at the top. Children are added to a parent upon creation, and parents will keep a reference to it’s child ThreadGroups, until the child is destroyed by a call to destroy(). This means that if java.lang.ThreadGroup is subclassed, and that subclass is loaded inside your application and instantiated, then there will be a strong reference to your applications classloader until that ThreadGroup is destroy()ed.

Known offenders

Among the API:s that are known to cause classloader leaks, without providing a proper cleanup/workaround, are a couple of JDK classes with the habit of keeping a reference to the contextClassLoader of the Thread that first calls them. The solution in this case is to make sure these methods are called once, with some other classloader – such as ClassLoader.getSystemClassLoader() – as contextClassLoader. Preferrably we put this code in the contextInitialized() method of our ServletContextListener. See Tomcats JreMemoryLeakPreventionListener class for more details.

Apache ActiveMQ

Apache ActiveMQ registers org.apache.activemq.util.StringArrayEditor as a property editor for String[] in java.beans.PropertyEditorManager (by a static block in org.apache.activemq.util.IntrospectionSupport), but provide no means of deregistering it. Reported here.

Apache Axis

Apache Axis leaks classloaders because of uncleared ThreadLocal, at least version 1.4, as we saw in part IV.

Apache Batik

Some versions of Batik SVG Toolkit (at least 1.5 beta 4 up to 1.7), leaves unterminated threads, as we saw in part III. It has been reported but at the time of this writing there is still no fix.

Apache Commons Pool / DBCP

Apache Commons Pool, which is used by Apache Commons DBCP, has a feature to automatically evict idle objects, which use a background thread running in the applications classloader. Earlier versions suffered from a bug, that did not allow the thread to be stopped properly (missing synchronization or volatile, like talked about in part III). See this blog post. It seem that in recent versions you can simply call org.apache.commons.pool2.impl.GenericObjectPool.close() at application shutdown. You can also turn off the idle evict feature at any time by calling org.apache.commons.pool2.impl.GenericObjectPool.
setTimeBetweenEvictionRunsMillis()
with a negative value.

Apache CXF

Apache CXF may set org.apache.cxf.transport.http.CXFAuthenticator as the default java.net.Authenticator; see above. (Thanks to Arild Froeland for the report!) Reported here.

Bean Validation API / JSR 303

The Bean Validation API / JSR 303 will leak classloaders, if the API is at the application server level while the implementation, such as Hibernate Validator, is included inside your web application. More details in part II.

CGLIB / Hibernate / Spring / JBoss / Apache Geronimo

CGLIB, used by Hibernate, Spring etc, has had a bug in it’s proxy code, with uncleared ThreadLocals (see part IV). Bug report on Hibernate. Bug reports on Spring. Bug report on JBoss. Bug report on Apache Geronimo.

dom4j

dom4j has uncleared ThreadLocals (see part IV). Reported here. That bug report is still “open”, but on other parts of the net report it to be fixed in 1.6.1.

com.sun.jndi.ldap.LdapPoolManager

The contextClassLoader of the thread loading the com.sun.jndi.ldap.LdapPoolManager class may be kept from being garbage collected, since it will start a new thread if the system property com.sun.jndi.ldap.connect.pool.timeout is set to a value greater than 0.

EclipseLink

The EclipseLink JPA implementation has had classloader leaks. According to this bug report fixed since version 1.1.

GeoTools

GeoTools is reported here to have unending thread. As of version 2.6.2 you should call org.geotools.util.WeakCollectionCleaner.exit() in your cleanup.

Google Guice

Googles IoC/DI framework Guice seems to have had several classloader leaks, at least some of which are not resolved at the time of this writing. Reports here, here and here.

Groovy

Groovy can cause classloader leaks according to this bug report, which is still “open”.

Hessian

Hessian binary web service protocol has suffered from uncleared ThreadLocals (see part IV). Bug reported here. Should be fixed since version 4.0.23 shipped with Resin.

iCal4J

iCal4J seems to have sufferend from uncleared ThreadLocals (see part IV). More info here.

Infinispan

Infinispan has had a number of reports of uncleared ThreadLocals. Two examples here and here, but there are more if you look at “Similar Issues” or search Jira yourself.

IntrospectionUtils

IntrospectionUtils copied from Tomcat (org.apache.tomcat.util.IntrospectionUtils) to Apache Commons Modeler (org.apache.commons.modeler.util.IntrospectionUtils) keeps a strong reference cache. After this was reported as a bug, a static clear() method has been added. Make sure to call it on application shutdown.

Java Advanced Imaging (JAI)

Java Advanced Imaging (JAI) library can cause classloader leaks with registered shutdown hooks, as we saw in part II. Bug report here – still “open”.

java.awt.Toolkit.getDefaultToolkit()

The first calll to java.awt.Toolkit.getDefaultToolkit() will spawn a new thread with the same contextClassLoader as the caller.

Javassist

I’ve seen reports on the net about PermGen errors when using older versions of Javassist for example with Hibernate. There are lots of issues in Javassist JIRA; start here and see “Similar Issues”. Since the issues have different fixed versions, you better use the latest version.

Java Cryptography Architecture (JCA) / MessageDigest initialization

According to Tomcat documentation, a Token poller thread with the same contextClassLoader as the caller, will be created “under certain conditions” when Java Cryptography Architecture is initialized, for example when a MessageDigest is created.

Java Server Faces 2

The JSF API, more precisely javax.faces.component.UIComponentBase, contains a cache that may cause classloader leaks in case the API is at the application server level. More information in this bug report.

javax.imageio / sun.awt.AppContext.getAppContext() / GWT

There will be a strong reference to the classloader of the calls to sun.awt.AppContext.getAppContext(). Note that Google Web Toolkit (GWT) will trigger this leak via its use of javax.imageio.

javax.management.remote.rmi.RMIConnectorServer.start() / sun.misc.GC.requestLatency(long)

sun.misc.GC.requestLatency(long), which is known to be called from javax.management.remote.rmi.RMIConnectorServer.start(), will cause the current contextClassLoader to be unavailable for garbage collection.

javax.security.auth.Policy

javax.security.auth.Policy.getPolicy() will keep a strong static reference to the contextClassLoader of the first calling thread.

javax.security.auth.login.Configuration

The class javax.security.auth.login.Configuration will keep a strong static reference to the contextClassLoader of Thread from which the class is loaded.

JGroups

JGroups may cause classloader leaks due to undestroyed custom ThreadGroups. At the time of this writing this issue has been fixed, while this one has not.

Logback

Logback causes classloader leaks when using SocketAppender according to this report, in which is it not really clear whether it has been fixed.

Logback also seems to have suffered from uncleared ThreadLocals (see part IV), as of this report. However that should be fixed since version 0.9.26.

JAXB

javax.xml.bind.DatatypeConverterImpl in the JAXB Reference Implementation shipped with JDK 1.6+ will keep a static reference (datatypeFactory) to a concrete subclass of javax.xml.datatype.DatatypeFactory, that is resolved when the class is loaded (which I believe happens if you have custom bindings that reference the static methods in javax.xml.bind.DatatypeConverter). It seems that if for example you have a version of Xerces inside your application, the factory method may resolve org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl as the implementation to use (rather than com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl shipped with the JDK), which means there will a reference from javax.xml.bind.DatatypeConverterImpl to your classloader.

Mojarra

If the Mojarra JSF implementation is provided by the application server, and you have JSF components included in your .war file, Mojarra may cause classloader leaks by keeping references to the components when application is redeployed. See bug report here.

Mozilla Rhino

The Rhino JavaScript interpreter has suffered problems related to ThreadLocals. You can read about the details in this blog post. The bug report states that it’s fixed (supposedly in 2005), but not from which version.

MVEL

MVEL expression language enginge has problems with uncleared ThreadLocals. The problem was adressed but version 2.0.19 still leaks, due to a static block adding an MVEL class as a ThreadLocal value. Current bug report here.

OpenOffice Java Uno RunTime (JURT)

The JURT (Java Uno RunTime) library in the OpenOffice UDK contains a peculiar leak. In an effort to avoid OutOfMemoryErrors(!) caused by long-running finalize methods, they created the com.sun.star.lib.util.AsynchronousFinalizer class, which holds a queue of jobs to be executed by a Thread. The problem is that this thread is never allowed to finish, as we talked about in part III. What makes this particularly tricky is that we don’t have any handle to the thread, and not least the fact that jobs are put on queue, and the thread is started if not yet running, from the finalize() method of other objects. That is, the thread may be started only when other objects are garbage collected, which may – at least in theory – not be until after your web application has been already unloaded! This problem has been reported here.

Oracle JDBC

Oracle JDBC driver, at least in some versions (such as ojdbc6), have a timeout detection thread, oracle.jdbc.driver.OracleTimeoutPollingThread, that according to reports has as its context classloader the classloader of the web application from which the first JDBC connection is requested, even if the driver itself resides on the server level. It seem this can be prevented by loading the class oracle.jdbc.driver.OracleTimeoutThreadPerVM using the system classloader before any JDBC connections are opened, which can be achieved in contextInitialized() of our ServletContextListener. (Thanks to Hal Deadman for the report!)

Serialization

Up to Java 1.4.2, serialization of classes loaded by your web apps classloader would cause reference to your classloader most likely to be kept by internal JDK caches. More info in this blog post. Bug report here.

Spring framework

Springs use of InheritableThreadLocal has caused leaks. Fixed since 1.2.9 / 2.0.1.

sun.java2d.Disposer

Loading the class sun.java2d.Disposer will spawn a new thread with the same contextClassLoader. More info.

sun.net.www.http.KeepAliveCache

In order to close reusable HTTP 1.1 connections after a timeout, sun.net.www.http.KeepAliveCache starts a thread which will keep a strong reference to the classloader from which the HTTP connection was initiated (through a ProtectionDomain). See more info in this blog post. According to Magnus Alvestads article, the thread will terminate eventually, which may cause intermittent classloader leaks. There is also no known solution, unless you have control over the server end and can add “Connection: close” to the HTTP responses.

Unified Expression Language

Up until version 2.2, the javax.el.BeanELResolver class of the Java Unified Expression Language / javax.el API kept a static strong reference cache with bean classes that had been introspected. This was reported as a leak and has since been fixed by using soft references in the cache, but at the time of this writing, there is no release including the fix. For currently released versions, the authors have been kind enough to provide a purgeBeanClasses() method to clear the cache, however this method is both private and non-static… (The JavaDoc of the method is a bit of a funny read, as it suggests the authors realized the problem, but failed to provide a proper solution.)

URLConnection

The caching mechanism of JarURLConnection can prevent JAR files to be reloaded. See this bug report. It is not entirely clear whether this will actually leak classloaders.

XML parsing

The classloader of the first thread to call DocumentBuilderFactory.newInstance().newDocumentBuilder() seems to be unable to garbage collection. Is it believed this is caused by some JVM internal bug.

Your Application Server

Yes, unfortunately the Application Server itself can be the cause of your classloader leaks. Tomcat (reports here, here, here), Jetty (here) and Resin (reports here, here, here, and more) has been know to suffer from such bugs, but there may be others as well. (There is a report on GlassFish here, but it’s not clear whether the error was actually within GlassFish.)

Pick the right Garbage Collector

It seems that for some reason, the default Garbage Collector of the Sun/Oracle JVM is not your best bet when it comes to freeing up permanent generation space. Assuming you have a multi core/multi CPU server (and who doesn’t these days?) I suggest you consider the Concurrent Mark and Sweep (CMS) Garbage Collector instead (but make sure you read up on the implications first). The CMS Garbage Collector however needs to be explicitly told to unload classes from PermGen space. Use these JVM options:

-XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled

Depending on your JVM version, you may also need -XX:+CMSPermGenSweepingEnabled. Try them out and keep an eye on the console/log file during startup to see if the JVM accepts them.

For further reading on different Garbage Collectors, see here.

Links to all parts in the series

Part I – How to find classloader leaks with Eclipse Memory Analyser (MAT)

Part II – Find and work around unwanted references

Part III – “Die Thread, die!”

Part IV – ThreadLocal dangers and why ThreadGlobal may have been a more appropriate name

Part V – Common mistakes and Known offenders

Part VI – “This means war!” (leak prevention library)

Presentation on Classloader leaks (video and slides)

Classloader leaks IV – ThreadLocal dangers and why ThreadGlobal may have been a more appropriate name

0

In the series on classloader leaks, it’s time to talk about ThreadLocals. As you know, java.lang.ThreadLocal provides a means to achieve thread safety in a multi-threaded environment, such as a web application. They can also be used to allow a thread access to some data in all layers of an application.

However, unless used correctly ThreadLocals are also a common cause of classloader leaks in web application environment. This is because Application Servers use thread pools, which means that a Thread may very well outlive your web application instance. So in case a ThreadLocal has a reference to something inside your classloader, there is a great risk that it will prevent your classloader from being garbage collected and you end up with java.lang.OutOfMemoryError: PermGen space. So in a web application environment, ThreadLocals should rather be considered to be ThreadGlobals, since it’s best to assume they will remain as long as the Application Server is running unless explicitly remove()d.

Avoid leaks caused by ThreadLocals

The most straightforward way to avoid this problem, is to enclose all your ThreadLocal usage in a try/finally block and make sure you remove the value before the Thread is returned to the thread pool.

try {
  threadLocal.set(value);
  ...
}
finally {
  threadLocal.remove();
}

When and why it leaks

You may think that java.lang.ThreadLocal is implemented with a WeakHashMap with Thread as key. If that was the case, they would probably have been less likely to cause classloader leaks, since all references would be cleared as the ThreadLocal instance was garbage collected.

But instead, ThreadLocal uses the Thread as storage. To be exact, java.lang.Thread has a threadLocals attribute of type java.lang.ThreadLocal.ThreadLocalMap. That is a Map with a WeakReference to the ThreadLocal instance as key and the threads value as value.

Some people claim, that using custom ThreadLocal subclasses loaded by your webapp classloader will cause leaks, however I have been unable confirm that. To me it seems the WeakReference of the key does it’s job.

However ThreadLocal values loaded by our classloader, including values with strong references to such classes (for example a List of our own classes) are likely to cause leaks. This is due to two facts. The first and obvious is that the references from the Thread to the value are strong references. But then you might ask, isn’t the strong value reference removed when the WeakReference key is garbage collected? Well, like with WeakHashMap the values are not immedately removed. WeakHashMap however uses a java.lang.ref.ReferenceQueue to keep informed about what keys have been removed, and internally calls the private expungeStaleEntries() when servicing any public method call. ThreadLocalMap however does not use a ReferenceQueue and thus removes the unused values much more rarely and unpredictably, as stated by it’s JavaDoc:

However, since reference queues are not used, stale entries are guaranteed to be removed only when the table starts running out of space

Third party example analyzed in Eclipse Memory Analyzer

Here is what an uncleared ThreadLocal can look like in a MAT analysis:
ThreadLocal analysis
This however does not show what causes the problem. In order to find that, make note of the entry index in brackets (38 in our case) and right click the ThreadLocal and select “List objects”, “with outgoing references”
ThreadLocal analysis 2
Find the correct entry with the index from the previous list
ThreadLocal analysis 3
At this stage, “referent” is the ThreadLocal instance and “value” is the value for the Thread. In this case we are lucky, in that a custom ThreadLocal subclass is used, so we can easily see what is causing the problem. In case no subclass is used, we could have right clicked the “referent” and selected “List objects”, “with incoming references” to see what class holds the ThreadLocal
ThreadLocal analysis 4

In this case, the problem is within Apache Axis, version 1.4. Looking at the source code of org.apache.axis.utils.XMLUtils we can confirm that it uses as custom ThreadLocal, kept in the static documentBuilder attribute.

    private static class ThreadLocalDocumentBuilder extends ThreadLocal {
        protected Object initialValue() {
            try {
                return getDOMFactory().newDocumentBuilder();
            } catch (ParserConfigurationException e) {
                log.error(Messages.getMessage("parserConfigurationException00"),
                        e);
            }
            return null; 
        }
    }     
    private static ThreadLocalDocumentBuilder documentBuilder = new ThreadLocalDocumentBuilder(); 

Which fails to be cleared:

    public static DocumentBuilder getDocumentBuilder() throws ParserConfigurationException {
        return (DocumentBuilder) documentBuilder.get();
    }

(Note that get() will set the value to what is returned by the overridden initialValue().)

Preventing ThreadLocal leaks

Trying to fix ThreadLocal leaks out of your control during application shutdown is not a very good idea due to concurrency issues. Instead you need to take care of the problem while the thread is still under your control, before it is returned to the thread pool. We can achieve this using a Servlet Filter. In the case above we have a static reference to the offending ThreadLocal. We could therefore create a filter like the following one. (Note that the code has been simplified in that all exceptions have been ignored and null is assumed to be returned instead. This of course will not compile, but hopefully makes the principle clearer.)

public class ThreadLocalLeakPreventionFilter implements javax.servlet.Filter {
  
  private ThreadLocal[] offendingThreadLocals;

  public void init(FilterConfig filterConfig) throws ServletException {
    List<ThreadLocal> threadLocals = new ArrayList<ThreadLocal>();

    // TODO: Needs error handling!!!
    Class clazz = Class.forName("org.apache.axis.utils.XMLUtils");
    if(clazz != null) {
      final Field threadLocalField = 
          clazz.getDeclaredField("documentBuilder");
      if(threadLocalField != null) {
        threadLocalField.setAccessible(true);
        Object threadLocal = threadLocalField.get(null);
        if(threadLocal instanceof ThreadLocal) {
          threadLocals.add((ThreadLocal)threadLocal);
        }
      }
    }
    
    // TODO: Look up more offenders here
    
    this.offendingThreadLocals = 
        threadLocals.toArray(new ThreadLocal[threadLocals.size()]);
  }

  /** 
   * In the doFilter() method we have a chance to clean up the thread
   * before it is returned to the thread pool 
   */
  public void doFilter(ServletRequest servletRequest, 
                       ServletResponse servletResponse, 
                       FilterChain filterChain) 
      throws IOException, ServletException {
    
    try {
      filterChain.doFilter(servletRequest, servletResponse);
    }
    finally {
      // Clean up ThreadLocals
      for(ThreadLocal offendingThreadLocal : offendingThreadLocals) {
        offendingThreadLocal.remove(); // Remove offender from current thread
      }
    }
  }

  public void destroy() {
    offendingThreadLocals = null; // Make available for Garbage Collector
  }
}

In case there was no static reference to the ThreadLocal to grab hold of, we could have looped the entries of the ThreadLocalMap via reflection in the doFilter() method, and looked for entries where either key or value is of a type loaded by the web app classloader. I might get back and show you exactly what that would look like.


Links to all parts in the series

Part I – How to find classloader leaks with Eclipse Memory Analyser (MAT)

Part II – Find and work around unwanted references

Part III – “Die Thread, die!”

Part IV – ThreadLocal dangers and why ThreadGlobal may have been a more appropriate name

Part V – Common mistakes and Known offenders

Part VI – “This means war!” (leak prevention library)

Presentation on Classloader leaks (video and slides)

Classloader leaks III – “Die Thread, die!”

2

In my previous post we looked at different categories of ClassLoader leaks, and looked at a particular example of a reference from outside the web application ClassLoader (a JVM shutdown hook pointing to a JAI class).

In this post we will look at another category; unterminated Threads running in your ClassLoader. This is a problem you can easily create yourself, but it may also come from third party libraries.

MAT analysis with running thread

When doing the “load all classes from third party JARs” test mentioned in my former post, and analyzing it with the technique outlined in my first post, I also ended up with this finding:

Batik analysis

As you can see, it is a thread still running inside my ClassLoader. We can also see, that the thread seems to be part of the Batik library. I was using version 1.5 beta 4, so let’s dig into the sources.

org.apache.batik.util.SoftReferenceCache (from line 181):

    private static Thread cleanup;

    static {
        cleanup = new Thread() {
                public void run() {
                    while(true) {
...
                    }
                }
            };
        cleanup.setDaemon(true);
        cleanup.start();
    }

org.apache.batik.ext.awt.image.rendered.TileMap (from line 139):

    static Thread cleanup;

    static {
        cleanup = new Thread() {
                public void run() {
                    while(true) {
...
                    }
                }
            };
        cleanup.setDaemon(true);
        cleanup.start();
    }

So, what do we have here? Not one but two static blocks (executing as the class is loaded) starting threads that execute in a while(true) loop. Once such a Threads is started, there is no garbage collecting their ClassLoader – neither the ClassLoader having loaded the Thread class (if a custom subclass to java.lang.Thread), nor the Threads contextClassLoader. In theory, the contextClassLoader of the thread can be changed (although I believe that rarely makes sense), but to garbage collect the ClassLoader of a custom Threads subclass, the thread must stop executing.

In newer versions of Batik, the two pieces of code above have been merged together into a new class – org.apache.batik.util.CleanerThread. That’s good. What’s not good is that there is at the time of this writing still a while(true) loop… This problem has been reported, and a patch has been proposed.

Stopping the thread – gangsta style

Fortunately, a referece to the thread is held in both SoftReferenceCache and TileMap (as can be seen above). In the new CleanerThread, there is also a static reference:

public class CleanerThread extends Thread {

    static volatile ReferenceQueue queue = null;
    static CleanerThread  thread = null;

That enables us to get hold of the Thread instance using reflection (same as with the shutdown hook in the former post) and call stop() on the Thread. Note that stop() is deprecated, since it may lead to an incosistent state. (You can read more about that in the Thread.stop() JavaDoc and the document that is linked from there.)

In our case however, leaking ClassLoaders and the eventual java.lang.OutOfMemoryError: PermGen space is a bigger problem than any inconsistent state that – if it occurs – presumably affects the abandoned instance of our web application. The best thing we can do in a generic case, is give the thread a chance to finish execution first. So in the cleanup Servlet/context listener we looked at last time, we will add this method, and call it once for every thread that needs to be stopped.

public static void forceThreadStop(Thread thread) {
  thread.interrupt(); // Make Thread stop waiting in sleep(), wait() or join()

  try {
    thread.join(2000); // Give the Thread 2 seconds to finish executing
  } catch (InterruptedException e) {
    // join failed
  }

  // If still not done, kill it
  if (thread.isAlive())
    thread.stop();

Stopping threads gracefully

In case you spawn threads from your own code, you should make sure that there is either a definitive ending point for them or, in case they need to be executed over and over again like a watchdog thread as in the case with Batik, that there is a way to gracefully tell to Thread to stop executing.

So, instead of the while(true), you should have a boolean flag that can be altered in order to tell the thread it’s time to die.

public class MyThread extends Thread {

  private boolean running = true;

  public void run() {
    while(running) {
      // Do something
    }
  }

  public void shutdown() {
    running = false;
  }
}

It is very important to note however, that the above code is likely to still leak ClassLoaders. This is because the JVM may cache the value of fields per thread, which Heinz Kabutz explains in somewhat more detail in The Java Specialists’ Newsletter edition titled “The Law of the Blind Spot”.

As Heinz shows, the easies solution is probably to add the volatile keyword.

public class MyThread extends Thread {

  private volatile boolean running = true;

  public void run() {
    while(running) {
      // Do something
    }
  }

  public void shutdown() {
    running = false;
  }
}

I encourage you to read Heinz’s entire article.

That’s all for this time. Until next post, good luck killing those threads!

Links to all parts in the series

Part I – How to find classloader leaks with Eclipse Memory Analyser (MAT)

Part II – Find and work around unwanted references

Part III – “Die Thread, die!”

Part IV – ThreadLocal dangers and why ThreadGlobal may have been a more appropriate name

Part V – Common mistakes and Known offenders

Part VI – “This means war!” (leak prevention library)

Presentation on Classloader leaks (video and slides)

Go to Top