When we are working on JavaEE, we will always has multiple issues related to classes and ClassLoader
.
We may struggle to find some strange memory leaks caused by ClassLoader
; we may fail to run some applications because it fail to find some class; we may encounter cases when multiple versions of library conflict.
In order to solve all similar problems one for all, today we focus the understanding of two exception (to be precise, one exception and one error):
java.lang.ClassNotFoundException
java.lang.NoClassDefFoundError
ClassLoader
Before we get to solve the problem, we have to skim some basic knowledge of class loading.
In the world of Java, almost all things are abstracted into a class. Class
is also a class, which organized by classpath and package structure. In order to load classes when suitable, JVM use the abstraction of ClassLoader
to locate or generate data that constitutes a definition for the class.
The class loader use the a model called delegation, in which a class loader will delegate the search for class/resources to its parent before attempting to find them by itself. The most basic class, like class under java.*
are all loaded by bootstrap class loader, which can’t be written in Java (or who will load this class?) and is the ancestor of all other class loaders. Other common class loaders are extension class loader and system class loader.
Class Not Found
From the doc of this ClassNotFoundException
:
Thrown when an application tries to load in a class through its string name using:
- The forName method in class
Class
. - The findSystemClass method in class
ClassLoader
. - The loadClass method in class
ClassLoader
.
but no definition for the class with the specified name could be found.
This doc sum up the three way to load a class in JVM, but it doesn’t tell us what does it mean and when it will be thrown.
The common way for class loader to work is to read a “class file” from directory specified by classpath, so this means that exception indicates the class was not found on the classpath. This indicates that we were trying to load the class definition, and the class did not exist on the classpath.
So, when this exception occurs, it may be means:
- we have wrong class path specified;
- we forget the full package name, which is required for class loader object to search in right directory;
- we don’t have the permission on some directory or file
No Class Def Found
From NoClassDefFoundError
:
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.
The docs points out the core of this error: this code can compile, but fail to run. It can have following possible reasons:
- the lib required is provided in compile classpath, but not provided in runtime environment – this error should be caused by a
ClassNotFoundException
:- lib is not packaged into Jar/War
- wrong class path settings in IDE and/or wrong class path environment variable
- access class across different class loaders
- this error is a subclass of
LinkageError
, so it will throw when:- when init class, i.e. init static variable or execute static code block and meet some errors with
ExceptionInInitializerError
- other verification error of class: illegal name, class file not match its binary name etc.
- when init class, i.e. init static variable or execute static code block and meet some errors with
Ref
- Great explanation about this differences
- JLS 5.4.1 class loading, linking and initialing
- Many examples of NoClassDefFoundError
Written with StackEdit.
评论
发表评论