views:

1028

answers:

3

What would cause a jar to be added successfully to an Eclipse Java project but then at runtime some of the classes from that jar are not found with ClassNotFound exceptions?

+4  A: 

The CLASSPATH variable at runtime is likely set incorrectly or you missed adding some classes to your jar file.

ojblass
I unzipped the jar and looked through it - I see the class in there. As for the Classpath, I thought Eclipse automatically takes care of that when you add a jar to your project under the Libraries tab of the Java Build Path -> that's where I added it using "Add external jar". So you're saying that's not enough - I can't trust Eclipse to know that this also needs to be added to the classpath?
Michael Jay
Java is a complex beast so your use of the word link in the question throws off the discussion. At its heart the jar file is just a zip file. Depending on how you import the classes and the directory structure of your jar file adding the toplevel jar file may simply not be enough... Are these classes by any chance anonymous inner classes?
ojblass
@Michael, how are you running the application?
matt b
There's a distinct difference between making a JAR available at compile-time and making it available at run-time
matt b
No the class in question is not an anonymous inner class - just your plain vanilla kind. For what it's worth, its the Google Guice framework and the class is called com.google.inject.Module. I was just trying to add this framework to an open source project that required it but did not provide it as part of its own source. I've spent the entire day trying different ways to get these two to build. But that's besides the point-based on the new information I gave you it's probably not the CLASSPATH?
Michael Jay
Under "Run Configurations" I see the guice.jar in the Classpath section as well as in the Source tab ("Source Lookup Path").
Michael Jay
When you added the .zip file to your application you likely had to right click it and do something that modified how the javac command resolved classes. The big quesiton is really the one matt is asking... how are you trying to run it? The location you imported it into could be important. Also try and take that same zip file and append it to the class path when you are running your jar.
ojblass
The run configurations only apply to within Eclipse...
ojblass
IT WORKED!!! HOLY MOTHER OF GOD!! Ok, I assumed that what I see in my Project Explorer is the same set of jars that is used to run the project but, no, that would be too easy. After I added the same jars under the Run Configurations/Classpath tab/Bootstrap Entries, it worked. I can't thank you enough for your help with this. Almost gave up on the whole project.
Michael Jay
StackOverflow at its finest!
ojblass
It's a curious thing, though. Now the jar files are listed twice under the Classpath tab - once under "bootstrap entries" section (the new addition that got it to work) and once under "user entries" (where it was listed all along). The "user entries" seem to come from the project settings that you need for compilation. But it was only after I duplicated the jars in the "bootstrap entries" that it worked. Not sure I understand why I needed to 'duplicate' the jar entries.
Michael Jay
I think that the boot strap entries might get put into the jar file in some special area that gets checked... Java has moved a long way since I used IDEs... see the comment under John's answer. I manage a lot of build processes and tend to err on eplicity setting things rather than paying any attention to features that make things work by magic. My guess is that the bootstrap stuff comes into some jar mystic property that gets populated.
ojblass
Your idea about the bootstrap entries adding metadata to the jar is an interesting theory. I added a new question to see if anyone has any more information on this since my Google research didn't turn up much. http://stackoverflow.com/questions/764725/whats-the-difference-between-classpath-bootstrap-entries-and-user-entries-in-ecl
Michael Jay
+2  A: 

@ojblass almost certainly has it right. Just to extend it, you can dump the jar file with the jar(1) tool and see if the class is there. I've had surprises from Eclipse where the project definition didn't understand what was to go into a jar file I was generating to run with java -jar.

Charlie Martin
On that topic I am dying to know if I can export what eclipse thinks the project should be built like... I hate headless builds...
ojblass
I unzipped the jar and looked through it - I see the class in there. As for the Classpath, I thought Eclipse automatically takes care of that when you add a jar to your project under the Libraries tab of the Java Build Path -> that's where I added it using "Add external jar". So you're saying that's not enough - I can't trust Eclipse to know that this also needs to be added to the classpath?
Michael Jay
@oj, I hate IDEs in general. @Michael, tell us how you're running the program. If it's with 'java -jar' then it *should* be working, making me suspect you're running from the command line with -classpath, or haven't told Eclipse to run as a jar file, and Eclipse is generating the -classpath form.
Charlie Martin
Also if you can run the stuff in eclipse it may be a good idea to maybe look at Run As... definitions for some hints.
ojblass
@ojblass - Under "Run Configurations" I see the guice.jar in the Classpath section as well as in the Source tab ("Source Lookup Path").
Michael Jay
@Charlie - to be honest, I don't even know whether it's java -jar or -classpath. I just configured the "Run Configurations" and click the Run button.
Michael Jay
@Michael, there is a project setting to let you make the classpath settings explicit. I can't tell you exactly where as I dn't have Eclipse installed here (see above, I hate IDEs) but IF you're running it in Eclipse AND you're getting that error, THEN you have something munged in your project setup.
Charlie Martin
Thanks Charlie. Got it working. After I added the jars to my runtime configuration (what looks like duplicate entries actually!), it worked. Made the mistake of thinking that my compilation settings are also used at runtime. I just assumed Eclipse was smart enough to bring that information over to the run settings. Thanks for your feedback.
Michael Jay
Eclipse 3.5M6 can build an executable jar with supportive jars from a launch configuration. VERY handy.
Thorbjørn Ravn Andersen
+2  A: 

Everybody seems to be on the right track. Why don't you, while you have the jar unzipped, add the entire thing as a source folder in your eclipse project to see if you can even load it that way? Sometimes, depending on the classloader, you can get the CNFE if your class is available multiple times on the classpath... the classloader just bails because it doesn't know which one to use.

John Ellinwood
Would it not simply take the first one it finds from the classpath?
ojblass
You would thing so, but I believe I ran into at least the classloader used in Sybase Jaguar that would bail on duplicated classpath entries instead of taking the first one
John Ellinwood
I will have to file that one away... You know that might explain some hack job I had to do for an JDBC project... I swear my eyes were bleeding at the time.
ojblass
Now that it's working thanks to everyone's help, I'm kind of wondering why it didn't work before because now the jar files are listed twice under the classpath tab - once under "bootstrap entries" and once under "user entries". The user entries seem to come from the project settings that you need for compilation. But it was only after I duplicated the jars in the "bootstrap entries" that it actually worked. Not sure why this would be. Any ideas on that?
Michael Jay
I think the bootstrap adds some meta information to jars... ears, wars, and jars all have files or properties within them that get autochecked at runtime... I avoid IDEs and little defaulting nits to the point of it being a religion. I explicity avoid any nicities an IDE gives me and make my code both at compile time and at runtime so explicit that it boarders on tedious
ojblass