log4j和线程上下文类加载器 [英] log4j and the thread context classloader

查看:440
本文介绍了log4j和线程上下文类加载器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Java的新手,刚刚开始弄清楚类加载器的概念。现在我对log4j有一些关于它使用线程上下文类加载器的问题。

I'm a newbie to Java and just starting to figure out the concept of class loaders. Right now I am having some issues with log4j regarding its use of the thread context classloader.

我收到以下错误: Aorg .apache.log4j.ConsoleAppender对象不能分配给org.apache.log4j.Appender变量。类org.apache.log4j.Appender由[java.net.URLClassLoader@105691e]加载,而类型为org.apache.log4j.ConsoleAppender的对象由[sun.misc.Launcher$AppClassLoader@16930e2]加载。无法实例化名为CONSOLE的appender。

我的应用程序大致采用这种方式:在init上构建URLClassLoader#1并加载一些类,这些类使用log4j。后来构建了URLClassLoader#2(它的URLClassLoader#1作为它的父级)并加载了更多的类,这些类也使用log4j。当URLClassLoader#2用于加载这些类时,会出现上述错误消息(还有一些问题出现在同一个问题上)。

My application works roughly this way: On init URLClassLoader #1 is constructed and loads some classes, these classes use log4j. Later on URLClassLoader #2 is constructed (which has URLClassLoader #1 as it's parent) and loads some more classes, these classes also use log4j. When URLClassLoader #2 is used to load these classes the above error message appears (there are a couple more with the same issue).

我当前的解决方法是设置在加载有问题的类之前将当前线程上下文类加载器设置为URLClassLoader#2,然后将其重置为旧类:

The current workaround I did was to set the current thread context classloader to URLClassLoader #2 before loading the problematic classes, and resetting it to the old one afterwards:

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

虽然这有效,但我不确定这是否正确。

While this works, I am not sure if it's the right approach.

对此问题的任何见解将不胜感激。另外,为什么log4j迫使我搞乱线程上下文类加载器?为什么不让我传入一个类加载器(当我不使用时使用默认的加载器)而不是使用该线程的一个?

Any insight on this matter will be appreciated. Also, why is log4j forcing me to mess with the thread context classloader? Why not let me pass in a class loader (and use a default one when I don't) instead of using the thread's one?

推荐答案

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

You appear to have stumbled upon the major problem with log4j (and the Apache Commons Logging library), namely that they have a ridiculously hard time discovering and interacting with the right classloaders as they're being used. There's a very dense explanation, complete with examples, here; the take-home message is that one of the primary driving forces for the new logging framework SLF4J was to eliminate these issues entirely. You might want to swap it in and see if your life is made any easier.

这篇关于log4j和线程上下文类加载器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆