java - Apache Avro ThreadLocal 对象在 Tomcat 未部署时徘徊

标签 java tomcat avro

我们使用 Apache Avro 作为我们的 Python 应用程序和我们在 Tomcat 服务中运行的一些第三方 Java 库之间的 JSON 接口(interface)。我们决定简单地扩展 org.apache.avro.ipc.ResponderServlet 类来实现我们自己的 servlet。 servlet 非常简单,因为它在构造函数中实例化 ResponderServlet 父类(super class),并覆盖 init() 和 destroy() 方法来为我们在 servlet 中运行的第三方库做一些内务处理。

然而,当 Tomcat 取消部署我们的 web 应用程序时,我们看到许多警告 ThreadLocal 相关内存泄漏的严重错误。

SEVERE: The web application [/hotwire] created a ThreadLocal with key of type [org.apache.avro.Schema$3] (value [org.apache.avro.Schema$3@4464784f]) and a value of type [java.lang.Boolean] (value [true]) 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.
Jan 24, 2013 2:19:36 AM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/hotwire] created a ThreadLocal with key of type [org.apache.avro.generic.GenericDatumReader$1] (value [org.apache.avro.generic.GenericDatumReader$1@2016ad9d]) and a value of type [org.apache.avro.util.WeakIdentityHashMap] (value [org.apache.avro.util.WeakIdentityHashMap@30e02ee0]) 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.

我们可能在某个地方做了一些幼稚的事情,因为我们无法在网络上的任何地方找到任何关于这种情况的帮助。尽管如此,我们还是希望有人能告诉我们哪里出了问题。

下面是我们的 servlet 的一瞥。

public class HotWire extends ResponderServlet{
    public HotWire() throws IOException
    {
              super(new SpecificResponder(Engine.class, new EngineImpl()));
    }

    @Override
        public void init() {
        try {
         super.init();
                 try {
                      init_engine();                
                      } catch (EngineInitException e) {
                      e.printStackTrace();
                      }
            } catch (ServletException e) {
                 e.printStackTrace();
            }
        }

        @Override
        public void destroy() {
            super.destroy();
            shutdown_engine();
        }

        public static class EngineImpl implements EngineInterface  {
            public Boolean create(Parameters message) {
                Boolean status = null;
                try {
                    status = engine.create_object(message);
                } catch (SemanticException | IOException e) {
                    e.printStackTrace();
                }
                return status;
            }

}

最佳答案

我遇到了类似的问题。如果你看这里有一个静态的 ThreadLocal 缓存,它被填满而无法删除它:

https://github.com/apache/avro/blob/master/lang/java/avro/src/main/java/org/apache/avro/generic/GenericDatumReader.java#L106

  private static final ThreadLocal<Map<Schema, Map<Schema, ResolvingDecoder>>> RESOLVER_CACHE = ThreadLocal
      .withInitial(WeakIdentityHashMap::new);

在我的例子中,每个请求都有不同的模式,因此我的 Spring Boot 服务最终会耗尽内存并终止。

这也是一个类加载器泄漏的例子: ThreadLocal & Memory Leak

我可以在这里看到一个 JIRA 请求改进: https://issues.apache.org/jira/browse/AVRO-1595

更新:我能够解决内存泄漏问题。有一个 ExecutorService 正在重用线程。现在我关闭了导致线程完成的服务。这允许对 ThreadLocal 内存进行 GC。

正如有人指出的那样,RESOLVER_CACHE 使用了一个 WeakIdentityHashMap,它应该允许对缓存进行 GC,但这对我来说并没有发生。

关于java - Apache Avro ThreadLocal 对象在 Tomcat 未部署时徘徊,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14522161/

相关文章:

java - Apache Tomcat 错误 http 状态 404

java - 我应该如何本地化数据库中始终必须为英文的系统字符串?

java - Tomcat 8 : HTTP Status 405 - HTTP method GET is not supported by this URL

java - Avro - 如何为 SpecificCompiler 注册自定义 LogicalType

scala - 如何确保持续生成 Avro schema 并避免 'Too many schema objects created for x' 异常?

java - Hortonworks 架构注册表 + Nifi + Java : Deserialize Nifi Record

java - 使用java程序进行电子邮件验证

java - JaxB处理子元素的方法

linux - Tomcat 文件夹的正确文件夹权限是什么?

java - 如何防止 Spring Boot Tomcat Jackson 中 flushBuffer 的并发锁定?