• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
  • Paul Clapham
  • Liutauras Vilda
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
Bartenders:

Ant and log4j problem

 
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
author
Posts: 5856
7
Android Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
omkar patkar
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 231
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 5856
7
Android Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Proudly marching to the beat of a different kettle of fish... while reading this tiny ad
Smokeless wood heat with a rocket mass heater
https://woodheat.net
reply
    Bookmark Topic Watch Topic
  • New Topic