Ceki Gülcü wrote:

At 12:08 10.01.2003 -0700, Gary Clayburg wrote:

Thanks for your quick reply. Also, thanks for creating and maintaining a great logging tool!

You are welcome.

I checked my classpath and I am only using one log4j.jar file. But even if there were two jar files on the classpath, that wouldn't cause this problem. The problem lies in how two different log4j configuration classes are loaded, namely org.apache.log4j.Appender and org.apache.log4j.ConsoleAppender. These classes are most definitely being loaded by different classloaders, as is evident in the error message.

There is a misunderstanding here. I did not ask whether you had
log4j.jar multiple times on the classpath. I asked whether you had
log4j.jar in the classpath *and* also had log4j.jar available
*directly* to the junit.runner.TestCaseClassLoader.

Which version of Junit is this? Is there any documentation on the
class loading model of Junit?

As for your question why log4j uses the TCL, the answer is that for
the J2EE platform using the TCL is less problematic than using
Class.forName even if both are ultimately problematic. The TCL is the
lesser evil.

--
Ceki

The version of Junit I am using is 3.8.1, which is the latest. The Junit classloader is basically a custom classloader that loads classes from the same place as the system classloader, which is ultimately the $CLASSPATH. So basically, because of the design of this particular classloader, log4j classes are capable of being loaded by either classloader - which of course is part of the problem.


But after digging further, I noticed in the source of for Junit, they never call Thread.currentThread().setContextClassLoader(loader). Without this being set, log4j can only use the default loader for this thread, which fails. In fact, by adding this line to the junit.runner.TestCaseClassLoader constructor, all the problems go away:

/**
* Constructs a TestCaseLoader. It scans the class path
* and the excluded package paths
*/
public TestCaseClassLoader() {
this(System.getProperty("java.class.path"));
System.out.println("creating new TestCaseClassLoader");
Thread.currentThread().setContextClassLoader(this);
}

The orignial constructor did not have the setContextClassLoader() method.


So I guess the question is, should log4j assume that frameworks such as junit call setContextClassLoader() when they create new classloaders? Or should log4j itself attempt to use the same classloader as was used for the org.apache.log4j.Appender class?



--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to