jxls 2.3.0 memory leak when using on Tomcat

Issue #54 resolved
Taro App
created an issue

When using jxls 2.3.0 on Tomcat, the following error appears on redeploying an application:

06-Jul-2016 11:05:48.761 SEVERE [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [ROOT] created a ThreadLocal with key of type [org.jxls.expression.JexlExpressionEvaluator$1] (value [org.jxls.expression.JexlExpressionEvaluator$1@1581a13]) and a value of type [org.apache.commons.jexl2.JexlEngine] (value [org.apache.commons.jexl2.JexlEngine@1b9cc5c]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.

06-Jul-2016 11:05:48.761 SEVERE [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [ROOT] created a ThreadLocal with key of type [org.jxls.expression.JexlExpressionEvaluator$2] (value [org.jxls.expression.JexlExpressionEvaluator$2@afb79]) and a value of type [java.util.HashMap] (value [{ ... }]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.

This indicates that jxls causes memory leak. Investigating the source code, I found that the source of the memory leak is JexlExpressionEvaluator class having references to JexlEngine and Expression as ThreadLocal. The ThreadLocal references are never cleared. I think the fix would be not to use ThreadLocal in JexlExpressionEvaluator, or to clear the ThreadLocal in an appropriate time such as in Transformer.write().

Related discussion: https://groups.google.com/d/topic/jxls/aoWFNqg-2h8/discussion

Comments (3)

  1. leonate NA repo owner

    There is now an alternative implementation of ExpressionEvaluator named JexlExpressionEvaluatorNoThreadLocal.

    To use it just set it in the transformation config

    transformer.getTransformationConfig().setExpressionEvaluator(new JexlExpressionEvaluatorNoThreadLocal());
    
  2. Log in to comment