What kind of class-loading error do you see when you develop an
application or start an installed application?
ClassCastException
A class cast
exception results when the following conditions exist and can be corrected
by the following actions:
- The type of the source object is not an instance of the target
class (type).
- This is the typical class cast exception. You can diagnose whether
the source object of a cast statement is not an instance of the target
class (type) by examining the class signature of the source object
class, then verifying that it does not contain the target class in
its ancestry and the source object class is different than the target
class. You can obtain class information by inserting a simple print
statement in your code. For example:
System.out.println( source.getClass().getName() + “:” + target.getClass().getName() );
Or
use a javap command. For example:javap java.util.HashMap
Compiled from "HashMap.java"
public class java.util.HashMap extends java.util.AbstractMap
implements java.util.Map,java.lang.Cloneable,java.io.Serializable {
- The class loader that loaded the source object (class) is different
from the class loader that loaded the target class.
- Assuming that the type of the source object is an instance of
the target class, a class cast exception occurs when the class loader
that loaded the source object's class is different that the class
loader that loaded the target class. This condition might occur when
the target class is visible on the classpaths of more than one class
loader in the WebSphere® Application Server runtime
environment. To correct this problem, use the Search and Search by
class name console pages used to diagnose problems with class loaders:
- Click to access the Search page.
- For Search type, select Class/Package.
- For Search terms, type the name of the
class that is loaded by two class loaders.
- Click OK. The Search by class name page
is displayed, listing all class loaders that load the class.
If
there is more than one class loader listed, then the target class
was loaded by more than one class loader. Because the source object
is an instance of the target class, the class loader that loaded the
source object class is different from the class loader that loaded
the target class.
- Return to the Class loader
viewer page and examine the classpath to determine why two
different class loaders load the class.
- Correct your code so that the class is visible only to the appropriate
class loader.
- The application fails to perform or improperly performs a narrow
operation.
- A class cast exception can occur because, when the application
is resolving a remote enterprise bean (EJB) object, the application
code does not perform a narrow operation as required. The application
must perform a narrow operation after looking up a remote object.
Examine the application and determine whether it looks up a remote
object and, if so, the result of the lookup is submitted to a narrow
method.
The narrow method must be invoked according to the EJB 2.0
programming model. In particular, the target class submitted to the
narrow method must be the exact, most derived interface of the EJB.
This also causes a class cast exception in the WebSphere Application Server runtime environment.
Examine the application and determine whether the target class submitted
to the narrow method is a super-interface of the EJB that is specified,
not the exact EJB type; if so, modify the application to invoke narrow
with the exact EJB interface.
Lastly, if a class cast exception
occurs during a narrow operation, verify that the narrow method is
being applied to the result of a remote EJB lookup, not to a local
enterprise bean. A narrow is not used for local lookups. Examine the
application or module deployment descriptor to ensure that the object
being narrowed is not a local object.
ClassNotFoundException
A class
not found exception results when the following conditions exist and
can be corrected by the following actions:
- The class is not visible on the logical classpath of the context
class loader.
- The class not found is not in the logical class path of the class
loader associated with the current thread. The logical classpath is
the accumulation of all classpaths searched when a load operation
is invoked on a class loader. To correct this problem, use the Search
page to search by class name and by Java archive
(JAR) name:
- Click to access the Search page.
- For Search type, select Class/Package.
- For Search terms, type the name of the
class that is not found.
- Click OK. The Search by class name page
is displayed, listing all class loaders that load the class.
- Examine the page to see if the class exists in the list.
- If the class is not in the list, return to the Search page. For Search
terms, type the name of the .jar file
for the class; for Search type, select JAR/Directory.
- Click OK. The Search by Path page is displayed,
listing all directories that hold the JAR file.
If the JAR file is not in the list, the class likely is not
in the logical class path, not readable or an alternate class is already
loaded. Move the class to a location that enables it to be loaded.
- The application incorrectly uses a class loader API.
- An application can obtain an instance of a class loader and call
either the loadClass method on that class loader, or it can call Class.forName(class_name, initialize, class_loader)
with that class loader. The application may be incorrectly using the
class loader application programming interface (API). For example,
the class name is incorrect, the class is not visible on the logical
classpath of that class loader, or the wrong class loader was engaged.
To
correct this problem, determine whether the class exists and whether
the application is properly using the class loader API. Follow the
steps in The class is
not visible on the logical classpath of the context class loader to
determine whether the class is loaded. If the class has not been loaded,
attempt to correct the application and see if the class loads. If
the class is in the class path with proper permission and is not being
overridden by another factory class, examine the API used to load
the class.
- Click to access the class loader Search page.
- For Search type, select Class/Package.
- For Search terms, type the name of the
class.
- Click OK. The Search by class name page
is displayed, listing all class loaders that load the class.
- Examine the page to see if the class exists in the list.
- If the class is in the list and a ClassNotFound exception was
thrown, then the .jar file or class is not in
the correct context or a wrong API call in the current context was
used.
If the class is not in the list, return to the Search page
and do the following:
- Search for the class that generated the exception; that is, the
class calling Class.forName.
- See which class loader loads the class.
- Determine whether the class loader has access or can load the
class not found by evaluating the class path of the class loader.
- A dependent class is not visible.
- When a class loader clsldr loads a class cls,
the Java virtual machine (JVM) invokes clsldr to
load the classes on which cls depends. Dependent classes must
be visible on the logical classpath of clsldr, otherwise an
exception occurs. This condition typically occurs when users make WebSphere Application Server classes visible
to the JVM, or make application classes visible to the JVM or to the WebSphere extensions class loader. For
example:
- Class A depends on Class B.
- Class A is visible to the WebSphere extensions class loader.
- Class B is visible on the local classpath of a WAR module class
loader, not the WebSphere extensions class loader classpath.
When the JVM loads class A using the WebSphere extensions
class loader, it then attempts to load Class B using the same class
loader and ultimately creates a class not found exception.
To
correct this problem:
- Make the application-specific classes visible to the appropriate
application class loader.
- Search for the class not found (Class B).
- If Class B is in the proper location, search for the class that
loads the dependent class (Class A) in the Class loader viewer.
- If the class is loaded and a ClassNotFound exception was thrown,
then the .jar file or class is not in proper context or the
wrong API call in the current context was used.
If no class was
found, do the following:
- Search for the class that generated the exception; that is, the
class calling Class.forName.
- See which class loader loads the class.
- Determine whether the class loader has access or can load the
class not found by evaluating the class path of the class loader.
- Ensure that the caller class (Class B) is visible to the JVM or
WebSphere extensions class loader.
NoClassDefFoundException
A
no class definition found exception results when the following conditions
exist and can be corrected by the following actions:
- The class is not in the logical class path.
- Refer to ClassNotFoundException for
information.
- The class cannot load.
- There are various reasons for a class not loading. The reasons
include: failure to load the dependent class, the dependent class
has a bad format, or the version number of a class.
UnsatisfiedLinkError
A linkage
error results when the following conditions exist and can be corrected
by the following actions:
- A user action caused the error.
Several user actions can result in a linkage error:
- A library extension name is incorrect for the platform.
A library has the dynamic link library name library_name.dll.
A library has the name library_name.so or library_name.a.
- System.loadLibrary is passed an incorrect parameter.
To load a dynamic link library named Name.dll, Name has
to be passed to a loadLibrary call.
To load
a library named libName.so or libName.a, libName is
passed to the load library.
- The library is not visible.
- As a best practice, use the JVM class loader to find or load native
libraries. WebSphere Application Server prints
the Java library path (java.library.path) when
starting up. If the JVM class loader is intended to load the library,
verify that the path containing the native library file is in the
Java library path. If not, append the path to the platform-specific
native library environment variable or to the java.library.path system
property of the server process definition.
In general, the Java
virtual machine invokes findLibrary() on the class loader xxx that
loads the class that calls System.loadLibrary(). If xxx.findLibrary()
fails, the Java virtual machine attempts to find the library using
the JVM class loader, which searches the JVM library path. If the
library cannot be found, the Java virtual machine creates an UnsatisfiedLinkError
exception.
Thus, if a WebSphere class loader is intended to
find a native library myNativeLib, the library
must be visible on the nativelibpath of the class
loader that loads the class that calls System.loadLibrary(myNativeLib).
This practice is necessary or desirable in the following situation:
Native libraries for data source providers must
be visible on the nativelibpath of the WebSphere
extensions class loader. In this case, add the path containing the
native library to the Native library path setting
of the data source provider configuration.
- Shared libraries have a Native library path in
their configuration. Because shared libraries enable the versioning
of application-specific libraries, consider specifying the paths to
any native libraries used by the shared library code in the shared
library configuration.
Ensure that the correct WebSphere class loader loads the class
that calls System.loadLibrary() and that the native library is visible
on the Native library path setting.
- System.mapLibraryName returns the wrong library file.
- When loading a shared library, JVM calls mapLibraryName(libName)
to convert libName to a platform specific name. On AIX®, HP-UX
or Solaris operating systems, this call might return a file name with
the wrong extension (for example, libName.so rather
than libName.a). To debug this, write a program
to that calls System.mapLibraryName() and verify that it returns the
correct file name.
- The native library is already loaded.
- This condition can result from either of the following errors:
- User error
- Check for multiple calls to System.loadLibrary and remove any
extraneous calls.
- Error when an application restarts
- The JVM has a restriction that only one class loader can load
a native library at a time. An error results when an application restarts
before the garbage collector cleans up the class loader from the stopped
application. When the class that loads the native library moves,
all of the classes that depend on that native library and their dependencies
also must move.
To correct this condition, move the loading of the
native library to a class loader that does not reload:
- Locate all application classes that load native libraries or have
native methods.
- Identify any dependent classes for the classes in step 1, such
as logging packages.
- Create a server-associated shared library or an isolated shared
library.
- Move the JAR files loaded for classes in steps 1 and 2 from the
application to the shared library created in step 3.
- Save your changes.
- Redeploy the application and rerun the scenario.
Classes within server-scoped libraries are loaded once
for each server lifecycle, ensuring that the native library required
by the application is loaded once for each Java virtual machine, regardless
of the application's life cycle.
- A dependent native library was used.
- Dependent native libraries must be found or loaded by the JVM
class loader. That is, if a native library NL is
dependent on another native library, DNL, the JVM
class loader must find DNL on the Java library path. This is because
the JVM runs native code when loading NL; when it encounters the dependency
on DNL, the JVM native code can call only to the JVM class loader
to resolve the dependency. A WebSphere class loader cannot load a
dependent native library.
Modify the platform-specific environment
variable defining the Java library path (LIBPATH) to include the path
containing the unresolved native library.