At 09:03 AM 3/26/2004 -0500, you wrote:
Hi, Not quite. I normally would let this go, but this is such an important issue and we see so many problems related to it ;) Additions interspersed.
>ClassNotFoundException means that you were trying to dynamically load a >class at runtime using something like >Class.forName("com.mycompany.MyClass") and the class couldn't be found.
That's one way to get it: another is if the container tries to load a class and it's not found anywhere on the classpath.
>NoClassDefFoundError can be caused by a couple different things: > >1. An import in the class being loaded cannot be found
No, this is a ClassNotFoundException under nearly all circumstances. (Used to be ALL circumstances, but with AOP and bytecode manipulation now you can get really hairy corner cases).
Hmm... Here's a quote from Craig R. McClanahan from a while back on the Tomcat list (sorry, don't have the original source handy)....
<quote> If a class itself cannot be found, you will usually get a ClassNotFoundException. You're getting a NoClassDefFoundError exception instead, which means that your class was found, but one of the classes *it* depends on (i.e. imports) can not be found. </quote>
Was he wrong?
>2. The class being loaded which existed at compile time is now not found >at runtime.
Not quite, and since this is the most common I'll clear it up: a class matching the fully-qualified class name was found by the classloader, but does not provide the same interface accessibility as the class by the same name that was present at compile time. For example, the class at runtime is missing a method that was present at compile time, or had a public method changed to private. This is what happens, for example, if you compile classes with the servlet 2.4 API and use a servlet 2.3 jar at runtime.
I just experienced this today. I moved a class to another package. It exists in CATALINA_HOME/common/lib because it is a JNDI factory and the bean it returns so it can't exist in WEB-INF/ib. I forgot to update the one for Tomcat while I compiled against the bean in the new package. When I ran the app, I didn't get a ClassNotFoundException, I got a NoClassDefFoundError. There was no class by the bean's name in the new package at runtime, but it was there at compile time. This is an exact description on what I said above. Call me crazy, but I think I might be right here.
Besides, here's what the Javadoc says for NoClassDefFoundError...
<quote>
The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found.
</quote>
>A third possibility might be that there are multiple versions of log4j >being loaded by different classloaders, but I'm not totally confident that >I can describe exactly how this results in a NoClassDefFoundError. > >If Log4j is actually in this user's classpath, then I would suspect the >third case. Yoav, maybe you can explain that third case a bit better for >us?
Sure. And this is general, there's nothing here specific to log4j. When you have multiple versions of the same libraries (fully-qualified class names is what matters: jar names do not), the loading order becomes relevant. For example, if he has an old copy in $JAVA_HOME/jre/lib/ext (or any other directory designated as 'endorsed' in the java command line), and a more recent copy in his webapp's WEB-INF/lib folder, the older copy will get loaded first by J2EE containers (and subsets therefore, e.g. servlet containers). Because he compiled against the version in WEB-INF/lib, he gets a NoClassDefFoundError at runtime, as the version he compiled against doesn't match the version found at runtime.
This is evil in certain ways: for example, it might not be the user who placed the copy in $JAVA_HOME/jre/lib/ext. It may have been a sysadmin, another developer, another user, etc, and now it's forgotten.
The solution is not difficult: carefully scan the entire classpath for multiple versions of the library that's throwing a NoClassDefFoundError. Remove all copies except the one you want. Keep your classpath and environment as clean as possible, no extra jars.
easy when you control the environment, hard when you don't.
Sometimes there are complications, such as when users run on a container that provides a shared classloading facility (JBoss, Tomcat, others). It is nearly always in the user's best interest to not use this facility, but instead stick to the specification and bundle all needed libraries for his/her application in a WAR/EAR file. Alternatively, the container should provide documentation regarding loading order and classloader delegation.
I hear ya. ClassLoaders can be crazy in appservers. Tomcat is one of the best behaved I've seen. WebLogic is just nuts, if you ask me! Maybe I just don't have the experience with it, but it is just one annoying classloader issue after another. BEA, fix your "enterprise" server already. Sheesh!
I could go on further into the actual permanent generation meaning of the NoClassDefFoundError (which is suboptimally named IMHO), but I'll stop here ;)
Well, we can't rename the class, but Sun would do well to provide a few more than 67 words describing the class in the Javadoc.
Yoav Shapira
later,
Jake
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
