log4j和线程上下文类加载器

时间:2009-12-29 13:45:24

标签: java log4j classloader

我是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".

我的应用程序大致采用这种方式:在init上构造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迫使我搞乱线程上下文类加载器?为什么不让我传入类加载器(当我不使用时使用默认加载器)而不是使用线程的?

1 个答案:

答案 0 :(得分:15)

你似乎偶然发现了log4j(以及Apache Commons Logging库)的主要问题,即他们在使用时发现并与正确的类加载器进行交互时非常困难。有一个非常密集的解释,附有例子here;带回家的信息是,新的日志记录框架SLF4J的主要推动力之一就是完全消除这些问题。你可能想要交换它,看看你的生活是否变得更容易。