This week's book giveaways are in the Java EE and JavaScript forums.
We're giving away four copies each of The Java EE 7 Tutorial Volume 1 or Volume 2(winners choice) and jQuery UI in Action and have the authors on-line!
See this thread and this one for details.
The moose likes Ant, Maven and Other Build Tools and the fly likes Ant and log4j problem Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of The Java EE 7 Tutorial Volume 1 or Volume 2 this week in the Java EE forum
or jQuery UI in Action in the JavaScript forum!
JavaRanch » Java Forums » Engineering » Ant, Maven and Other Build Tools
Bookmark "Ant and log4j problem" Watch "Ant and log4j problem" New topic
Author

Ant and log4j problem

omkar patkar
Ranch Hand

Joined: Aug 25, 2005
Posts: 231
Hello friends,

I was trying a simple log4j program and using ant to compile and execute the program.
I somehow managed to execute the program, but it initially gave the problems.
I want to understand why after my last attempt the program got executed. Please can someone help me understand this.

Things that i am using:-
-------------------------------------------------
log4j version = 1.2.15
ANT version = 1.7.1
jdk version = 1.6
OS = Windows Vista Home Basic Edition.
-------------------------------------------------

I downloaded the log4j jar file. But as first step, i did not register it into the CLASSPATH environment variable.

First a look at the simple Java program that i wrote: -


Now using the <javac> task of ANT, i tried to compile....but it failed, as Logger class could not be found.

Therefore as first successfull step i registered, the log4j jar in the CLASSPATH environment variable.
After registering, when i ran the ant on the same build.xml it COMPILED SUCCESSFULLY !

Now, i went a step ahead to run the program using the <java> task of ANT.
This time it failed, saying

... "java.lang.NoClassDefFoundError: org/apache/log4j/Logger
at org.omkar.tester.Tester.<clinit>(Unknown Source)
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Logger
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
... 1 more"


....... isn't this incorrect ? ........ because log4j.jar has been registered in the CLASSPATH environment variable already, and a test of successful registration is that the compilation took place properly!

The <java> task in my build file looks like : -

So, another step forward, by reading the error i realized, that the the java needs to load the Log4j related classes only then my Tester class will execute.
So i modified my <java> task in build.xml to include the log4j.jar file (which i copied in lib directory inside my project folder) ..the modified target now looks as : -




.... interestingly now the Tester class got executed ! ... Initially why ANT did not pickup the log4j.jar from the CLASSPATH environment variable at the time of executing ?

I am wondering if at the time of compile it was possible for ANT to pick up the Log4j related classes from the log4j.jar, why it could not do so at the time of running the program ? Why there is a need to specify the log4j jar file explicitily at the time of executing ?

Thanks and Regards
Omkar Patkar


Thanks and Regards
Omkar Patkar (SCJP 1.4)[url]http://javacollectionsnotes.blogspot.com[/url] | [url]http://omkar-myscjpexp.blogspot.com[/url]
Peter Johnson
author
Bartender

Joined: May 14, 2008
Posts: 5823
    
    7

First, do not set CLASSPATH - that is a sure way to cause other problems down the road. I have several machines and CLASSPATH is not set on any of them and I run a multitude of Java apps.

And as you found, defining a path variable that includes the log4j.jar file and then referencing that path variable in both the javac and java tasks is the correct way to do this.

As to why the java task did not pick up your CLASSPATH value, it probably has something to do with classloaders and how Ant runs java apps internally and that the classpath is set specifically to what is defined in the java task for such apps.


JBoss In Action
omkar patkar
Ranch Hand

Joined: Aug 25, 2005
Posts: 231
Thank you for the reply Peter.

I think you are right, it has got something to do with the classloader.

What i did next was, i printed out the classloader being used, so i put following line in my Tester.java



When i run the build.xml (the one i modified to get successfull output!), it prints the classloader as :-



This means, the Sun Microsystem's VM's Classloader is not used. Immediately what i did next was, i ran the same program as a java command,
instead of running it as an ant task. So i executed the program as: -



When i do so, ... the program runs properly without any exception. The classloader displayed at this time is of Sun !



This time, when Tester was executed, as no exception was reported, that means, the Sun's classloader was able to find, necessary Log4j related classes
by looking into the CLASSPATH environment variable! (I found this by printing out the "java.class.path" system property and in case of Sun's classloader, it prints out my CLASSPATH environment variables, and in case of ANTCLASSLOADER, it prints the location where ONLY all the ant related jar files are present!)

... so i went a STEP further to understand the working of ANT.

I created another execute target in the build.xml, But this time i marked the "fork" attribute of this new target as "true" the build.xml looks as follows: -




I did this, so that instead of Ant's classloader .... the Sun's classloader is used, and that the log4j jar file will be picked up from the CLASSPATH directly.
In other words, i was expecting that "executeProject3" will run as if i ran the Tester class using the ordinary java command and that the program will run
successfully.

But i got the same exception as i got earlier of NoClassDefFound for the Logger class !

But surprisingly, although this time, the Sun's classloader is used, the CLASSPATH environment variable is not refered,
... even the system property "java.class.path" prints, the location that Ant class loader used to refer to !

Therefore, obviously, the program fails to execute.

Can someone please tell me, what happens when ANT is run, which paths are looked into, when and by which class loaders ?
Although, this is interesting....it is also confusing !

Thanks and Regards
Omkar Patkar
omkar patkar
Ranch Hand

Joined: Aug 25, 2005
Posts: 231
Any one ..... any idea as to what happens when ANT is run, which paths are looked into, when and by which class loaders ?

Thanks and Regards
Omkar Patkar
Peter Johnson
author
Bartender

Joined: May 14, 2008
Posts: 5823
    
    7

You got the same exception when you used fork because in that case Ant fired off a new JVM and passed a -classpath argument, and when the JVM sees --classpath it ignores the CLASSPATH env var.

I'm not sure why you are going through this exercise. When using an Ant task that accepts a classpath (or classpath ref) you should provide all of the classes required or you will get a class not found exception. This behavior is consistent and unambiguous.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Ant and log4j problem