我是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强制我弄乱线程上下文类加载器?为什么不让我传递类加载器(如果不使用,则使用默认的加载器)而不是使用线程的加载器?

最佳答案

您似乎偶然发现了log4j(和Apache Commons Logging库)的主要问题,即在使用它们时发现它们与正确的类加载器并与之交互非常困难。有一个非常密集的解释,包括here示例;传达的信息是,新日志记录框架SLF4J的主要插入力之一是完全消除这些问题。您可能想要交换它,看看您的生活是否变得更轻松。

10-06 05:00