Wednesday, October 20, 2010

NoClassDefFoundError

Introduction:
This is an error we sometimes encounter in test environment. From JDK description (since JDK1.0), the error is Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found. The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found (runtime).

Here are some cases of this error:
Case 1:
java.lang.NoClassDefFoundError: org/apache/log4j/Category) (Caused by org.apache.commons.logging.LogConfigurationException: No suitable Log constructor [Ljava.lang.Class;@2c773f1 for org.apache.commons.logging.impl.Log4JLogger (Caused by java.lang.NoClassDefFoundError: org/apache/log4j/Category))

Possible root cause: WebLogic cache somehow missed the class definition but didn't try to load it again.

The fix: Need a refresh to reload classes.
1.       Delete all the dir which named .wlnotdelete under beahome/ user_projects(or sub-dir)
2.       Delete all the files under upload dir under beahome/ user_projects(or sub-dir)
3.       Restart WLS and redeploy the package

Case 2:
java.lang.NoClassDefFoundError: Could not initialize class com.company.webapp.module.search.Proxy
com.company.webapp.module.search.Searcher.FTSearch(Searcher.java:141)
com.company.webapp.module.search.FullTextSearch.execute(FullTextSearch.java:104)
com.company.webapp.module.Exec.execute_local(Exec.java:876)
Root cause: new instance has dependency on service manager for search engine endpoint look-up. When service manager is down, the constructor will throw exception. 
The fix is to provide default value or not throw exception in constructor.
Case 3:
java.lang.NoClassDefFoundError: Could not initialize class com.company.webapp.module.search.PathCache$PathCacheHolder com.company.webapp.module.search.PathCache.getInstance(PathCache.java:139)

Root cause: In preload servlet, the init() method needs to call service manager (another application on the same JVM) for component endpoint look-up, it will slow down tomcat open ports (because tomcat opens ports only after all servlet/listener from web apps are initialized, in this case, preload servlet is still initializing while waiting for service manager). 
The fix is to use another thread in init() method with 30 seconds wait-time to call service manager to speed up tomcat startup. With that, preload servlet will get initialized very fast, and tomcat will open ports after the application (with preload servlet) and service manager (with other lightweight servlet) are ready in the same tomcat.
Case 4:
javax.servlet.ServletException: Servlet execution threw an exception
com.company.MyFilter.doFilter(MyFilter.java:30)
com.company.UtilFilter.doFilter(UtilFilter.java:64)
java.lang.NoClassDefFoundError: Could not initialize class

Possible root cause: Emma build somehow causes runtime issue though the compiling was ok. We once met similar issue (Emma build caused securityexception). The reason was there was no any change to application filters between 2 daily builds, so we were confident the error was not caused by code change, but by daily build. 
The fix was to use previous build or use non-Emma build.
To sum up:
NoClassDefFoundError is error and usually is caused by coding practice. However, sometime environment issue (like build or application server bug) might also cause this error. The way to fix it is to analyze the error log for root cause, then figure out a solution. One guideline is to ensure the jar or class is in the classpath, and the constructor (class) or init (servlet) or getInstance (for singleton class) doesn't depend on other resources.





No comments:

Post a Comment