Rabu, 26 Februari 2014

3 ways to solve java.lang.NoClassDefFoundError in Java J2EE




I know how frustrating is to see Exception in thread "main" java.lang.NoClassDefFoundError,  which is a manifestation of NoClassDefFoundError in Java. I have seen it couple of times and spent quite a lot time initially to figure out what is wrong , which class is missing etc. First mistake I did was mingling java.lang.ClassNotfoundException and NoClassDefFoundError, in reality they are totally different, and my second mistake was using trial and error method to solve this java.lang.NoClassDefFoundError instead of understanding why NoClassDefFoundError is coming, what is real reason behind NoClassDefFoundError and how to resolve this. In this Java tutorial I have tried to rectify that mistakes and uncover some secrets of NoClassDefFoundError in Java and will share my experience around it. NoClassDefFoundError is not something which cannot be resolved or hard to resolve it’s just its manifestation which puzzles most of Java developer. This is the most common error in Java development along with java.lang.OutOfMemoroyError: Java heap space and java.lang.OutOfMemoryError: PermGen space  Anyway let’s see Why NoClassDefFoundError comes in Java and what to do to resolve NoClassDefFoundError in Java.













What is reason of NoClassDefFoundError in Java?




NoClassDefFoundError in Java comes when Java Virtual Machine is not able to find a particular class at runtime which was available during compile time. For example if we have a method call from a class or accessing any static member of a Class and that class is not available during run-time then JVM will throw NoClassDefFoundError. It’s important to understand that this is different than ClassNotFoundException which comes while trying to load a class at run-time only and name was provided during runtime not on compile time. Many Java developer mingle this two Error and gets confused.





In short NoClassDefFoundError will come if a class was present during compile time but not available in java classpath during runtime. Normally you will see below line in log when you get NoClassDefFoundError:


Exception in thread "main" java.lang.NoClassDefFoundError



Exception in thread “main” simply indicate that its “main” thread which is not able to find a particular class it could be any thread so just don’t worry . Difference between this error coming in main thread and other thread is , when Exception in thread “main” comes program crashes or shut it self down as opposed to other thread in which case your program will continue to run.,









Difference between java.lang.NoClassDefFoundError and ClassNotFoundException in Java



Many a times we confused ourselves with java.lang.ClassNotFoundException and java.lang.NoClassDefFoundError, though both of them related to Java Classpath they are completely different to each other. ClassNotFoundException comes when JVM tries to load a class at runtime dynamically means you give the name of class at runtime and then JVM tries to load it and if that class is not found in classpath it throws java.lang.ClassNotFoundException. While in case of NoClassDefFoundError the problematic class was present during Compile time and that's why program was successfully compile but not available during runtime by any reason. NoClassDefFoundError is easier to solve than ClassNotFoundException in my opinion because here we know that Class was present during build time but it totally depends upon environment, if you are working in J2EE environment than you can get NoClassDefFoundError even if class is present because it may not be visible to corresponding class loader. See my post NoClassDefFoundError vs ClassNotFoundException in Java for more details.











How to resolve java.lang.NoClassDefFoundError in Java



java.lang.NoClassDefFoundError in Java solution Obvious reason of NoClassDefFoundError is that a particular class is not available in Classpath, so we need to add that into Classpath or we need to check why it’s not available in Classpath if we are expecting it to be. There could be multiple reasons like:





1) Class is not available in Java Classpath.




2) You might be running your program using jar command and class was not defined in manifest file's ClassPath attribute.




3) Any start-up script is overriding Classpath environment variable.


4) Because NoClassDefFoundError is a sub class of java.lang.LinkageError it can also come if one of it dependency like native library may not available.




4) Check for java.lang.ExceptionInInitializerError in your log file. NoClassDefFoundError due to failure of static initialization is quite common.




5) If you are working in J2EE environment than visibility of Class among multiple Classloader can also cause java.lang.NoClassDefFoundError, see examples and scenario section for detailed discussion.





We will now see couple of example and scenarios when java.lang.NoClassDefFoundError has came before and how its been resolved. This can help you to troubleshoot root cause of NoClassDefFoundError in Java application.








NoClassDefFoundError in Java - Example and Scenarios



1. Simple example of NoClassDefFoundError is class belongs to a missing JAR file or JAR was not added into classpath or sometime jar's name has been changed by someone like in my case one of my colleague has changed tibco.jar into tibco_v3.jar and by program is failing with java.lang.NoClassDefFoundError and I was wondering what's wrong.





2. Class is not in Classpath, there is no sure shot way of knowing it but many a times you can just have a look to print System.getproperty("java.classpath")and it will print the classpath from there you can at least get an idea of your actual runtime classpath.





3. Just try to run with explicitly -classpath option with the classpath you think will work and if its working then it's sure short sign that some one is overriding java classpath.








NoClassDefFoundError in Java due to Exception in Static Initializer block




This is another common reason of java.lang.NoClassDefFoundError, when your class perform some static initialization in static block like many Singleton classes initialized itself on static block  to take advantage of thread-safety provided by JVM during class initialization process, and if static block throw an Exception, the class which is referring to this class will get NoclassDefFoundError in Java. If you look at your log file you should watch for any java.lang.ExceptionInInitializerError because that could trigger java.lang.NoClassDefFoundError: Could not initialize class on other places. Like in below code example, During class loading and initialization User class is throwing Exception from static initializer block, which trigger ExceptionInInitializerError during first time loading of User class in response to new User() call. Later rest of new User() are failing as java.lang.NoClassDefFoundError. situation gets worst if original ExceptionInInitializerError, which is root cause here is silently eaten by any code.








Code Example of NoClassDefFoundError due to Static block Exception:







/**

 * Java program to demonstrate how failure of static initialization subsequently cause

 * java.lang.NoClassDefFoundError in Java.

 * @author Javin Paul

 */


public class NoClassDefFoundErrorDueToStaticInitFailure {



   
public static void main(String args[]){

       

        List
<User> users = new ArrayList<User>(2);

       

       
for(int i=0; i<2; i++){

           
try{

            users.
add(new User(String.valueOf(i))); //will throw NoClassDefFoundError

           
}catch(Throwable t){

                t.
printStackTrace();

           
}

       
}        

   
}

}



class User{

   
private static String USER_ID = getUserId();

   

   
public User(String id){

       
this.USER_ID = id;

   
}

   
private static String getUserId() {

       
throw new RuntimeException("UserId Not found");

   
}    

}





Output

java.lang.ExceptionInInitializerError

    at testing.NoClassDefFoundErrorDueToStaticInitFailure.main(NoClassDefFoundErrorDueToStaticInitFailure.java:23)

Caused by: java.lang.RuntimeException: UserId Not found

    at testing.User.getUserId(NoClassDefFoundErrorDueToStaticInitFailure.java:41)

    at testing.User.<clinit>(NoClassDefFoundErrorDueToStaticInitFailure.java:35)

    ... 1 more

java.lang.NoClassDefFoundError: Could not initialize class testing.User

    at testing.NoClassDefFoundErrorDueToStaticInitFailure.main(NoClassDefFoundErrorDueToStaticInitFailure.java:23)








5) Since NoClassDefFoundError is a  also a LinkageError which arises due to dependency on some other class , you can also get java.lang.NoClassDefFoundError if your program is dependent on native library and corresponding dll is not there. Remember this can also trigger java.lang.UnsatisfiedLinkError: no dll in java.library.path Exception Java. In order to solve this keep your dll along with JAR.





6) If you are using ANT build file create JAR and manifest file than its worth noting to debug till that level to ensure that ANT build script is getting correct value of classpath and appending it to manifest.mf file.





7) Permission issue on JAR file can also cause NoClassDefFoundError in Java. If you are running your Java program in multi-user operating system like Linux than you should be using  application user id for all your application resources like JAR files, libraries and configuration. If you are using shared library which is shared among multiple application which runs under different users  then you may run with permission issue , like JAR file is owned by some other user and not accessible to your application. One of our reader “it’s me said” faced java.lang.NoClassDefFoundError due to this reason. See his comment also.





8) Typo on XML Configuration can also cause NoClassDefFoundError in Java. As most of Java frameworks like Spring, Struts they all use xml configuration for specifying beans. By any chance if you put the bean name wrong, it may surface as java.lang.NoClassDefFoundError while loading other class which has dependency on wrongly named bean. This is quite common on Spring MVC framework and Apache Struts where you get tons of Exception in thread "main" java.lang.NoClassDefFoundError , while deploying your WAR or EAR file.





9) Another example of java.lang.NoClassDefFoundError as mentioned by our reader Nick is that when your compiled class which is defined in a package, doesn’t present in same package while loading like in case of JApplet it will throw NoClassDefFoundError in Java. Also see Nick’s comment on this error.





10) java.lang.NoClassDefFoundError can be caused due to multiple classloaders in J2EE environments. Since J2EE doesn’t mention standard class-loader structure and it depends upon different vendors like Tomcat, WebLogic, WebSphere on how they load different components of J2EE like WAR file or EJB-JAR file. In order to troubleshoot NoClassDefFoundError in J2EE application knowledge of How ClassLoader works in Java is mandatory. Just to recap ClasLoader works on three principle delegation, visibility and uniqueness. Delegation means every request to load a class is delegated to parent classloader, visibility means ability to found classes loaded by classloader, all child classloader can see classes loaded by parent classloader but parent classloader can not see the class loaded by child classloaders. Uniqueness enforce that class loaded by parent will never be reloaded by child clasloaders. Now suppose if a class say User is present in both WAR file and EJB-JAR file and loaded by WAR classloader which is child classloader which loads class from EJB-JAR. When a code in EJB-JAR refer to this User class, Classloader which loaded all EJB class doesn’t found that because it was loaded by WAR classloader which is child of it. 



This will result in java.lang.NoClassDefFoundError for User class. Also If class is present in both JAR file and you will call equals method to compare those two object, it will result in ClassCastException as object loaded by two different classloader can not be equal.







11) Some of reader of this blog also suggested that they get Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/tools/javac/Main , this error means either your Classpath, PATH  or JAVA_HOME is not setup properly or JDK installation is not correct. which can be resolved by re-installing JDK. IF you are getting this error try to reinstall JDK . One of our reader got this issue after installing jdk1.6.0_33 and then reinstalling JDK1.6.0_25, he also has his JRE and JDK on different folder. See his comment also by searching JDK1.6.0_33 .







12) Java program can also throw java.lang.NoClassDefFoundError during linking which occurs during class loading in Java. One of the example of this scenario is just delete the User class from our static initializer failure example after compilation and they try to run the program. This time you will get java.lang.NoClassDefFoundError directly without  java.lang.ExceptionInInitializerError and message for NoClassDefFoundError is also just printing name of class as testing/User i.e. User class from testing package. Watch out for this carefully as here root cause is absent of User.class file.


java.lang.NoClassDefFoundError: testing/User

    at testing.NoClassDefFoundErrorDueToStaticInitFailure.main(NoClassDefFoundErrorDueToStaticInitFailure.java:23)








Let me know how exactly you are facing NoClassDefFoundError in Java  and I will guide you how to troubleshoot it, if you are facing with something new way than I listed above we will probably document if for benefit of others and again don’t afraid with Exception in thread "main" java.lang.NoClassDefFoundError.  








Other Exception and Error handling Tutorials from Javareivisted































Source:http://javarevisited.blogspot.com/2011/06/noclassdeffounderror-exception-in.html

Tidak ada komentar:

Posting Komentar