Утечка в загрузчике веб-приложений в CORBA + Tomcat 6 + - PullRequest
2 голосов
/ 16 февраля 2012

РЕДАКТИРОВАТЬ :

Я обнаружил утечку загрузчика классов в своем веб-приложении.Это сводится к тому, что сторонняя библиотека инициализирует CORBA через службу имен COS JNDI и не подвергает вызов чистому закрытию контекста JNDI.Это оставляет некоторые связанные с CORBA потоки и другие ресурсы, ссылающиеся на мой загрузчик классов webapp и предотвращающие его сборку мусора.Это приводит к ошибке OutOfMemory: PermGen после нескольких повторных развертываний / перезагрузок.

На данный момент я увеличил объем памяти PermGen в JVM, и это увеличивает интервалы между сбоями сервера.Это, очевидно, не исправление, а обходной путь (и плохой в этом отношении).

Я предполагаю, что мой вопрос заключается в том, можно ли каким-то образом отключить JNDI-контекст без сохранения ссылки на него .Мои инстинкты говорят мне «нет», но, возможно, я не знаю о какой-то магической функции JNDI, которая позволила бы мне овладеть этим контекстом.

Таким образом, способ, которым сторонняя библиотека инициализирует объекты CORBA, является чем-то вроде этогостроки (обработка исключений и другие подробности опущены для краткости):

private CorbaObjectAggregate initCorba() {
    InitialContext ctx = null;
    CorbaObjectAggregate corbaObjects = new CorbaObjectAggregate();
    ORB orb = null;
    Properties env = getContextEnvironment();
    String[] args = null;
    orb = ORB.init(args, null);
    env.put("java.naming.corba.orb", orb);
    ctx = new InitialContext(env);
    //a bunch of object lookups follow
    corbaObjects.someCorbaObjectReference = (SomeCorbaObjectClass) ctx.lookup("somePaht");
    return corbaObjects;
}

Итак, ссылка на ctx исчезла после того, как этот метод завершил выполнение ...

Я попытался остановить потоки вручнуюно это не устранило утечку.Я предполагаю, что есть некоторые другие ресурсы corba, хранящие загрузчик классов.Полагаю, я мог бы попытаться выследить их каким-нибудь методом очистки и освободить загрузчик классов таким образом, но я надеялся на какое-то более чистое решение.

Просто для ясности, сторонняя библиотека с закрытым исходным кодом, и я могу 'это действительно не меняет.Это также не жизнеспособный вариант, чтобы получить поддержку от компании, стоящей за этим.

1 Ответ

1 голос
/ 28 марта 2012

Это будет сложно исправить. Вероятно, будут две проблемы: - классы, загруженные из JAR, содержащие ссылку на загрузчик классов веб-приложения - потоки, запущенные этим процессом, имеющие загрузчик классов веб-приложения в качестве загрузчика классов контекста.

Что-то вроде следующего должно помочь:

  1. Переместите JAR в $ CATALINA_BASE / lib. Это будет означать, что классы загружаются общим загрузчиком классов. Недостатком является то, что они также видны и доступны всем веб-приложениям.

  2. Узнайте, где в вашем приложении инициируется инициализация. Перед выполнением этого кода установите загрузчик класса контекста потока равным загрузчику класса системы (или родителю загрузчика класса текущего (веб-приложения)) и сбросьте загрузчик класса контекста потока после вызова init. Это должно означать, что любые созданные потоки не имеют загрузчика классов веб-приложений в качестве загрузчика классов контекста.

Если потоки создаются в другие моменты времени, исправить это может быть очень сложно, очень быстро.

Информацию, которая может помочь понять, что происходит, смотрите: http://people.apache.org/~markt/presentations/2010-11-04-Memory-Leaks-60mins.pdf

Чтобы увидеть, что Tomcat делает внутри для решения этих проблем, смотрите: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java?view=annotate

...