Мы используем Apache Avro в качестве интерфейса JSON между нашим приложением Python и некоторыми сторонними библиотеками Java, которые мы запускаем в службе Tomcat. Мы решили просто расширить класс org.apache.avro.ipc.ResponderServlet для реализации нашего собственного сервлета. Сервлет действительно прост, поскольку он создает экземпляр суперкласса ResponderServlet в конструкторе и переопределяет методы init() и destroy(), чтобы выполнять некоторую работу со сторонними библиотеками, которые мы запускаем в сервлете.
Однако, когда Tomcat отменяет развертывание нашего веб-приложения, мы видим ряд СЕРЬЕЗНЫХ ошибок, предупреждающих об утечках памяти, связанных с 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.
Вероятно, мы где-то делаем что-то наивное, потому что не смогли найти никакой помощи в Интернете для этого сценария. Тем не менее, мы надеемся, что кто-то здесь может сказать нам, где мы идем не так.
Вот беглый взгляд на наш сервлет.
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;
}
}