log4j и загрузчик классов контекста потока

Я новичок в Java и только начинаю понимать концепцию загрузчиков классов. Прямо сейчас у меня возникают некоторые проблемы с log4j, связанные с использованием загрузчика классов контекста потока.

Я получаю следующие ошибки: A "org.apache.log4j.ConsoleAppender" object is not assignable to a "org.apache.log4j.Appender" variable. The class "org.apache.log4j.Appender" was loaded by [java.net.URLClassLoader@105691e] whereas object of type "org.apache.log4j.ConsoleAppender" was loaded by [sun.misc.Launcher$AppClassLoader@16930e2]. Could not instantiate appender named "CONSOLE".

Мое приложение работает примерно так: при инициализации создается URLClassLoader # 1 и загружает некоторые классы, эти классы используют log4j. Позже создается URLClassLoader # 2 (который имеет URLClassLoader # 1 в качестве родительского) и загружает еще несколько классов, эти классы также используют log4j. Когда URLClassLoader # 2 используется для загрузки этих классов, появляется указанное выше сообщение об ошибке (есть еще пара с такой же проблемой).

Текущий обходной путь, который я сделал, заключался в том, чтобы установить текущий загрузчик классов контекста потока на URLClassLoader # 2 перед загрузкой проблемных классов и затем сбросить его на старый:

ClassLoader urlClassLoader; // this is URLClassLoader #2
Thread thread = Thread.currentThread();
ClassLoader loader = thread.getContextClassLoader();
thread.setContextClassLoader(urlClassLoader);
try {
  urlClassLoader.loadClass(...)
} finally {
  thread.setContextClassLoader(loader);
}

Хотя это работает, я не уверен, что это правильный подход.

Мы будем благодарны за любое понимание этого вопроса. Кроме того, почему log4j заставляет меня возиться с загрузчиком классов контекста потока? Почему бы мне не передать загрузчик классов (и использовать загрузчик по умолчанию, когда я этого не делаю) вместо использования загрузчика потока?


person Idan K    schedule 29.12.2009    source источник
comment
Вы спасли мне жизнь своим вопросом, я застрял на 3 дня с похожей проблемой! Я не установил thread.setContextClassLoader, и с этим все в порядке! Это действительно приятно, несмотря на то, что вы новичок в java!   -  person Daniel Hári    schedule 05.06.2016


Ответы (1)


Похоже, вы наткнулись на главную проблему с log4j (и библиотекой протоколирования Apache Commons), а именно на то, что им до смешного сложно обнаруживать нужные загрузчики классов и взаимодействовать с ними по мере их использования. Здесь есть очень подробное объяснение с примерами, здесь; можно сделать вывод, что одной из основных движущих сил для новой структуры ведения журналов SLF4J было устранение этих проблем полностью. Возможно, вы захотите поменять его и посмотреть, упростится ли ваша жизнь.

person delfuego    schedule 29.12.2009
comment
Я не уверен, возможно ли на данном этапе использовать что-то еще. Какой предлагаемый способ решения этой проблемы с log4j? - person Idan K; 29.12.2009
comment
Честно говоря, я не могу сказать, потому что это достаточно серьезная проблема, что я теперь старательно избегаю log4j и Apache Commons Logging. На самом деле, вы должны иметь возможность легко перейти на SLF4J - см. slf4j.org/legacy.html для получения информации о том, как SLF4J поставляется с мостовыми адаптерами, которые позволяют вашему коду по-прежнему выполнять вызовы log4j и перехватывать эти вызовы SLF4J. Таким образом, вы можете использовать SLF4J изначально в любом новом коде и перенести старый код, использующий log4j, на SLF4J на досуге. - person delfuego; 29.12.2009
comment
+1 за подсказку, чтобы избежать Log4j и JCL. Их заменяет SLF4j, который также имеет уровни совместимости для log4j и jcl. Мы сделали это во ВСЕХ наших проектах именно по этим причинам. - person mhaller; 29.12.2009
comment
есть ли у вас статьи, объясняющие, почему следует избегать использования log4j? Я действительно не могу придумать подобное предложение без некоторой предыстории. Также может помочь некоторая информация о том, что SLF4j является новым «стандартом». - person Idan K; 29.12.2009
comment
Дэниел, связанная статья (ссылка с подробным объяснением) объясняет проблему, и проблема, с которой вы сталкиваетесь, должна быть лучшим примером из всех. - person delfuego; 29.12.2009
comment
спасибо, я рассмотрю это и другие вопросы, касающиеся SLF4j на SO - person Idan K; 30.12.2009