Diagnosis of Java class loader memory leaks

IBM ClassLoader Analyzer

We will learn basic concept of class and class load mechanism, generate class/classloader leaks and diagnose problems with a variety of artifacts such as Java heap dump, Java class trace and IBM Javacore with IBM ClassLoader Analyzer.

Jinwoo Hwang, Senior Software Engineer, IBM

Jinwoo Hwang is a software engineer, an inventor, an author, and a technical leader at IBM WebSphere Application Server Technical Support in Research Triangle Park, North Carolina. He is the architect and creator of IBM HeapAnalyzer and many other technologies. He is the author of the book C Programming for Novices as well as numerous webcasts and publications. He is an IBM Certified Solution Developer, an IBM Certified WebSphere Application Server System Administrator, a SUN Certified Programmer for the Java platform and an IBM developerWorks Contributing Author. To learn more about his publications, webcasts and products visit JinwooHwang.com.



18 October 2013

Also available in Japanese

Introduction

Welcome to IBM ClassLoader Analyzer. This tool allows you to analyze Java classes, Java classloaders and libraries from Java classloader trace files and IBM javacore files. We will learn basic concept of class loader, class loading mechanism and policies. We will create test applications, generate class and classloader leaks and diagnose problems with a variety of artifacts such as Java heap dump, Java class trace and IBM Javacore with IBM ClassLoader Analyzer.

Note: This tool is provided “as is” without warranty of any kind, either express or implied, including, but not limited to, the implied warranties or conditions of non-infringement, merchantability or fitness for a particular purpose.

Prerequisites

  • The Java™ runtime environment version 6 or higher
  • Java class loader trace (-verbose:class) file
  • [Optional] Javacore from IBM Java virtual machine

Features

  • Calculation of number of classeloaders, classes and loaded libraries from javacore
  • Automatic detection of classloader leak suspects from javacore
  • Suspect view with total number of classes and loaded classes from javacore
  • Classloader and class tree view from javacore
  • Classloader view with loaded classes from javacore
  • Library tree view for classloaders from javacore
  • Automatic detection of javacore and classloader trace
  • Automatic detection of suspect classes loaded multiple times from classloader trace
  • Suspect class view from classloader trace
  • Jar and class tree view from classloader trace

Overview

What are Java class loaders?

When we start a Java runtime environment, the Java virtual machine locates and loads a group of classes such as bootstrap classes, extension classes and user classes. The bootstrap classes include classes that comprise the Java system platform and core Java libraries. The extension classes are optional packages of classes for application developers to extend the functionality of the core Java platform. The user classes are provided by application developers that do not fall into extension classes. Each set of classes is loaded by different class loaders. A class loader is responsible for locating the binary forms of classes and interfaces with given binary class name or interface names. A class loader uses a delegation model to locate classes, interfaces and resources. A class loader will delegate class and resource loading to its parent class loader before trying to load the class or resource itself by default.

In a Java virtual machine there are 3 class loaders: the bootstrap class loader for the bootstrap classes, the extensions class loader for extension classes, and the application class loader for user classes. The class loaders maintain hierarchical relationships among them. The extensions class loader is the parent for the application class loader. The bootstrap class loader is the parent for the extensions class loader. The bootstrap class loader does not have any parent class loader.

The bootstrap class loader loads classes and interfaces from the bootstrap path which is stored in the sun.boot.class.path system property. You can easily find out the path with the following Java code with the help of System API method, getProperty():

System.getProperty("sun.boot.class.path");

The exensions class loader loads classes and interfaces from extension directory. The location of the extension directory stored in the java.ext.dirs system property. It is implemented by the sun.misc.Launcher$ExtClassLoader class. The following Java code will return extension directory:

System.getProperty("java.ext.dirs");

The application class loader loads classes and interfaces from class path. The location of the clsss path is stored in the java.class.path system property. The application class loader is implemented by the sun.misc.Launcher$AppClassLoader class. The following Java code will return class path:

System.getProperty("java.class.path");

Java class loaders and their hierarchy
Java class loaders and their hierarchy

What are IBM WebSphere Application Server class loaders?

When we start the IBM WebSphere Application Server, the IBM WebSphere Application Server classes are loaded by a custom class loader, the IBM WebSphere extensions class loader. With a custom class loader, we can customize the class loader behaviors such as the delegation model. By default, as we learned previously classes are loaded by parent class loaders. But we can now change the delegation model to load classes in the current class loader first before delegating to its parent class loader with a custom class loader.

The classes associated with a Java EE application such as EJB modules, utility jar files, resource adapter archives and shared libraries are loaded by a WebSphere application class loader by default. You can also change configuration so that the WebSphere class loader can be shared by multiple applications. Java virtual machine’s application class loader is the parent for the WebSphere application class loader.

Each web module of a Java EE application is loaded by a WAR class loader but you can configure WAR class loader policy to share a WAR class loader for all web modules in an application. The WebSphere application class loader is the parent for the WAR class loader.

Java and IBM WebSphere Application Server class loaders and their hierarchy
Java and IBM WebSphere Application Server class loaders and their hierarchy

Run-time class vs. Compile-time class

One of the trickiest parts of having multiple class loaders is that you could load classes or interfaces with the same binary name on different class loaders.

If we have classes or interfaces with the same binary name, we say we have the same compile-time classes/interfaces.

Even though we have the classes or interfaces that have the same binary name, the same compile-time classes/interfaces, if they are loaded by different class loaders, they are different run-time classes.

When classes are loaded with the same binary name on the same class loader, they are the same run-time classes.

Test case I

Let’s build a custom class loader, LeakClassLoader to generate class and classloader leak. We could extend java.lang.ClassLoader to create a classloader but we will extend java.net.URLClassLoader to save time by overriding the loadClass method.

The loadClass method in java.lang.ClassLoader checks whether a class has already been loaded. If the class has not been loaded, the loadClass method delegates the search for the class to the parent classloader. If the class is not found by the parent class, the loadClass method invokes the method findClass for the current classloader to load the class.

In order to cause a leak on LeakClass, we will override the loadClass method of java.net.URLClassLoader in LeakClassLoader. This will prevent the parent classloader from searching for the LeakClass and invoke the method findClass for the current classloader to load the LeakClass. For other classes, the method loadClass calls the loadClass method of java.lang.ClassLoader.

Listing 1. LeakClassLoader.java
/*
 * Author : Jinwoo Hwang, jinwoo@us.ibm.com
 * LeakClassLoader.java
 * (C) Copyright IBM Corp. 2013
 */
package com.ibm.jinwoo.classloader.testcase;

import java.net.URL;
import java.net.URLClassLoader;

public class LeakClassLoader extends URLClassLoader {
	public LeakClassLoader() {
		super(new URL[] {
getContextClassLoaderClassPath()
});
	}
	
	@Override
	public Class<?> loadClass(String className) throws ClassNotFoundException {
if (className != null && className.equals("com.ibm.jinwoo.classloader.testcase.LeakClass")
                        ) {
			return findClass(className);
		} else {
			return super.loadClass(className);
		}
	}

	static URL getContextClassLoaderClassPath() {
		return Thread.currentThread().getContextClassLoader().getResource(".");
	}
}

In LeakTest.java, we will create new instances from InstanceGenerator’s newInstance method and add them to an ArrayList.

Listing 2. LeakTest.java
/*
 * Author : Jinwoo Hwang, jinwoo@us.ibm.com
 * LeakTest.java
 * (C) Copyright IBM Corp. 2013
 */
package com.ibm.jinwoo.classloader.testcase;

import java.util.ArrayList;

public class LeakTest {

public static void main(String[] args) 
throws IllegalAccessException,InstantiationException, ClassNotFoundException {
		ArrayList list = new ArrayList();
		while(true){
LeakClassInterface instance = InstanceGenerator.newInstance();

			list.add(instance);
		}
	}
}

In the newInstance() method of InstanceGenerator.java, we will create a new instance of LeakClassLoader, load the class LeakClass, create an instance of LeakClass and return it.

Listing 3. InstanceGenerator.java
/*
 * Author : Jinwoo Hwang, jinwoo@us.ibm.com
 * InstanceGenerator.java
 * (C) Copyright IBM Corp.
 */

package com.ibm.jinwoo.classloader.testcase;

public class InstanceGenerator {
	public static LeakClassInterface newInstance() throws IllegalAccessException,
			InstantiationException, ClassNotFoundException {
		
		LeakClassLoader classLoader = new LeakClassLoader();
		return (LeakClassInterface) 
		classLoader.loadClass("com.ibm.jinwoo.classloader.testcase.LeakClass")
.newInstance();
	}
}

LeakClass implements the interface LeakClassInterface.

Listing 4. LeakClass.java
/*
 * Author : Jinwoo Hwang, jinwoo@us.ibm.com
 * LeakClass.java
 * (C) Copyright IBM Corp. 2013
 */

package com.ibm.jinwoo.classloader.testcase;

public class LeakClass implements LeakClassInterface {

}

LeakClassInterface does not have any fields or methods.

Listing 5. LeakClassInterface.java
/*
 * Author : Jinwoo Hwang, jinwoo@us.ibm.com
 * LeakClassInterface.java
 * (C) Copyright IBM Corp. 2013
 */

package com.ibm.jinwoo.classloader.testcase;

public interface LeakClassInterface {

}

Now we have written all the classes and interfaces to create a class/classloader leak. Let’s compile the classes and run LeakTest:

java com.ibm.jinwoo.classloader.testcase.LeakTest

Class dump

In IBM Java runtime environment, we can take a class/class loader dump which is a part of IBM Java thread dump, javacore. Sending signal 3 to the Java process will trigger the dump. On Windows™ systems, you can use Ctrl-Break from Java console.

The following is an example of a class dump from IBM Javacore. Because it is a text file, we can easily understand the content of the class dumps but it is sometimes overwhelming to skim through thousands of lines of class and class loader entries.

Listing 6. Class dump from IBM Javacore
NULL           ------------------------------------------------------------------------
0SECTION       CLASSES subcomponent dump routine
NULL           =================================
1CLTEXTCLLOS  	Classloader summaries
1CLTEXTCLLSS	12345678: 1=primordial,2=extension,3=shareable,
4=middleware,5=system,6=trusted,7=application,8=delegating
2CLTEXTCLLOADER	p---st-- Loader *System*(0x000007FF7E855250)
3CLNMBRLOADEDLIB	Number of loaded libraries 3
3CLNMBRLOADEDCL	Number of loaded classes 438
2CLTEXTCLLOADER	-x--st-- Loader sun/misc/Launcher$ExtClassLoader
(0x000007FF7E859C10),Parent *none*(0x0000000000000000)
3CLNMBRLOADEDLIB	Number of loaded libraries 0
3CLNMBRLOADEDCL	Number of loaded classes 0
2CLTEXTCLLOADER	-----ta- Loader sun/misc/Launcher$AppClassLoader
(0x000007FF7E86FE50), Parent sun/misc/Launcher$ExtClassLoader(0x000007FF7E859C10)
3CLNMBRLOADEDLIB		Number of loaded libraries 0
3CLNMBRLOADEDCL		Number of loaded classes 4
…

Fortunately we have a tool for this. Let’s analyze class dumps with IBM ClassLoader Analyzer.

How to start the IBM ClassLoader Analyzer

We need to use the Java™ runtime environment version 6 or higher to run the IBM ClassLoader Analyzer.

Depending on the configuration of your system’s Java runtime environment, you could execute a jar file simply by just clicking on the file from your operating system’s graphical user interface or typing in the path name of the jar file from a command line interface just like an ordinary executable file.

If none of them seem to work, or you do not have time to configure your operating system, you need to use your command line interface.

Usage : <Java path>java –jar ica< version>.jar

For example, /usr/java/bin/java -jar ica101.jar will start version 1.0.1 of the IBM ClassLoader Analyzer with Java runtime launcher which is located in the directory, /usr/java/bin/.

How to use IBM ClassLoader Analyzer

When we first start the tool, we will have a chance to read and accept/decline license agreement.

License Agreement
License Agreement

If you decline the license agreement, the program will terminate and you should promptly return the unused media and documentation to the party from whom it was obtained for a refund of the amount paid. If the program was downloaded, destroy all copies of the program.

If you accept the license agreement, you should be able to see the following initial screen of the tool.

You can navigate the tool with menus, icons in tool bars or key short cuts for example key combination of control-X to exit from the tool. The console frame provides you with important messages from the tool.

If you accept the license agreement, you will be able to see the initial screen:

Initial Screen
Initial Screen

We need to open the javacore from File Menu.

How to use File menu

Under the File Menu, there are Open verbose:class/javacore, Close Files, Close All Files and Exit menu items.

File Menu
File Menu

Open verbose:class/javacore

If you select File->Open verbose:class/javacore menu item, you can analyze Java verbose class trace or IBM javacore files.

Open verbose:class/Javacore
Open verbose:class/Javacore

Select the javacore and click on the open button. There are Close Files, Close All Files and Exit menu below the Open menu item for later use:

Close Files

If you select File->Close Files, selected files are closed.

Close All Files

If you select File->Close All Files, all files are closed.

Exit

If you select File->Exit, the problem is terminated. Let’s go back to the javacore we just loaded.

File List

If the file is successfully loaded, you should be able to find the javacore in File List View with analysis.

File List
File List

At the bottom of property/value screen, you can see the following analysis result:

ClassLoader Leak Suspect
com/ibm/jinwoo/classloader/testcase/LeakClassLoader is loaded 2,185 times (99.82 %)

The tool identified a class/classloader leak suspect. The class, com/ibm/jinwoo/classloader/testcase/LeakClassLoader is loaded as many as 2,185 times which is 99.82% of total class loadings.

If you are not convinced and would like to get more information, select the dump in the File List and click on Analysis menu.

How to use Analysis menu

Under the Analysis menu, there are Suspect View, Tree View, ClassLoader View and Library View menu items.

Suspect View

If you select Analysis->Suspect View, you can see more about leak suspects.

Suspect View Menu
Suspect View Menu

The Suspect View indicates that the class, com/ibm/jinwoo/classloader/testcase/LeakClassLoader loaded 2,185(from the Classes column) classes. The class, com/ibm/jinwoo/classloader/testcase/LeakClass is the only class it loaded. The com/ibm/jinwoo/classloader/testcase/LeakClassLoader loaded 2,185(from the Count column) times responsible for 99.8% of total loaded classes.

Suspect View for LeakClassLoader
Suspect View for LeakClassLoader

In this simple test case, we have only 4 class loaders. The first one is com/ibm/jinwoo/classloader/testcase/LeakClassLoader that we just built. What about those 3 class loaders? Do you remember the Java class loaders we learned? We can see the bootstrap class loader(*System*), the extensions class loader (sun/misc/Launcher$ExtClassLoader) and the application class loader (sun/misc/Launcher$AppClassLoader) from the above table. You need to adjust the width of ClassLoader column to see the full class loader names.

If we had lots of class loaders, we could filter them out by taking advantage of “Search Class” with regular expressions at the bottom of the screen.

Let’s select the second classloader, sun/misc/Launcher$AppClassLoader just for comparison. sun/misc/Launcher$AppClassLoader is the application class loader in the Java virtual machine. sun/misc/Launcher$AppClassLoader loaded 4 classes and there is only 1 instance(count) of sun/misc/Launcher$AppClassLoader responsible for 0.046% of total classes.

On the right hand side of the screen, you can see total classes, the number of classes per class loader and list of loaded classes for the class loader:

Analysis of sun/misc/Launcher$AppClassLoader

PropertyValue
Total Classes4
Classes4 per ClassLoader com/ibm/jinwoo/classloader/testcase/InstanceGenerator
com/ibm/jinwoo/classloader/testcase/LeakClassInterface
com/ibm/jinwoo/classloader/testcase/LeakClassLoader
com/ibm/jinwoo/classloader/testcase/LeakTest
Suspect View for AppClassLoader
Suspect View for AppClassLoader

Tree View

Now let’s go back to Analysis menu and select Tree View to visualize class and class loader hierarchy.

Tree View Menu
Tree View Menu

In Tree View, we can easily find which classes are loaded from which class loaders.

Tree View, class loaders
Tree View, class loaders

We can see that com/ibm/jinwoo/classloader/testcase/LeakClassLoaders are loaded from sun/misc/Launcher$AppClassLoader.

Tree View, classes loaded from class loaders
Tree View, classes loaded from class loaders

Let’s expand com/ibm/jinwoo/classloader/testcase/LeakClassLoader.

We can see that LeakClass is loaded by LeakClassLoader which is loaded by AppClassLoader which is loaded by ExtClassLoader. The first column represents the number of classes loaded in current class loader and child class loaders. The second column in the brackets represents the number of classes loaded from the current classloader. The 3rd column shows the name of the class or class loader. The 4th column has the address of the class or the classloader. The last column shows the types of the class loaders. There are 8 characters to represent class loader types.

If there are no class types for a class loader, the 5th column would look like this:

Here is the list of type for each position:

1=primordial
2=extension
3=shareable
4=middleware
5=system
6=trusted
7=application
8=delegating

For the ExtClassLoader, we see -x--st— in the 5th column.

12345678 -x--st--

This means the ExtClassLoader is an extension (2/x), system (5/s) and trusted (6/t) class loader.

Let’s take a look at some of the class loader types you might encounter sooner or later.

Types of class loaders

  • Primordial class loader: Also known as bootstrap class loader. This class loader is responsible for loading only the classes that are from the core Java™ API. These classes are the most trusted and are used to bootstrap the JVM.
  • Extensions class loader: It can load classes that are in optional extensions packages in the extensions directory.
  • Shareable class loader: This class loader loads shared classes.
  • Middleware class loader: This class loader is responsible for loading middleware classes. Middleware objects have a life expectancy longer than a single transaction and that persist across JVM-resets.
  • System class loader: bootstrap class loader, extensions class loader and other Java system class loaders.
  • Application class loader: This class loader is responsible for loading classes from java.class.path. It runs in a restricted security context.

If you select LeakClassLoader, you can see details about the class loader in the property and value table on the right.

Tree View of LeakClassLoader
Tree View of LeakClassLoader

When a class is selected, you can find the class name and the address of the class in the window on the right.

Tree View of LeakClassLoader
Tree View of LeakClassLoader

ClassLoader View

Let’s select Analysis->ClassLoader View to show ClassLoader View.

ClassLoader View Menu
ClassLoader View Menu

From ClassLoader View, we can see classloaders, loaded classes and the number of loaded classes.

AppClassLoader loaded 2,190 classes
LeakClassLoader loaded 2,185 classes

ClassLoader View
ClassLoader View

If you select the AppClassLoader, you can find what classes are loaded from the AppClassLoader. We have 4 different classes loaded from the AppClassLoader and total 2,190 classes are loaded from the AppClassLoader.

ClassLoader View of AppClassLoader
ClassLoader View of AppClassLoader

Analysis of sun/misc/Launcher$AppClassLoader

PropertyValue
Loaded Classes2,190
Classes4
com/ibm/jinwoo/classloader/testcase/InstanceGenerator
com/ibm/jinwoo/classloader/testcase/LeakClassInterface
com/ibm/jinwoo/classloader/testcase/LeakClassLoader
com/ibm/jinwoo/classloader/testcase/LeakTest

Library View

If you select Analysis->Library View, you can see loaded libraries for classloaders.

Library View Menu
Library View Menu

We have 3 libraries loaded by *System* class loader.

Library View
Library View

No Javacore? No problem

On Non-IBM Java runtime environment

What if you do not have IBM Java runtime? You could use Java heap dumps which are widely available from a variety of Java runtime environment implementations. On most IBM Java platforms, a Java heap dump is generated automatically by default when you are running out of memory. On certain Java platforms, you will need to specify a command-line option.

For example on JVM from Oracle™, you need to use the command line option -XX:+HeapDumpOnOutOfMemoryError for the Java virtual machine to generate a Java heap dump when an OutOfMemoryError is thrown. That option was first introduced in Java 1.4.2 update 12 and Java 5.0 update 7 on Java platforms from Oracle™. So you probably should be able to use that option unless you have an antique Java virtual machine.

If you cannot just sit and wait for an OutOfMemoryError like me, you can force Java heap dumps. On IBM Java platforms, you can set the environment variable IBM_HEAPDUMP or IBM_HEAP_DUMP to TRUE and send a signal 3 to the Java process. On Java virtual machines from Oracle, you need to add an option such as -agentlib:hprof=heap=dump command line option to enable forced Java heap dump.

You can use your favorite Java heap analysis tool to analyze the Java heap dump. If you do not have one you can download a copy of IBM HeapAnalyzer (https://www.ibm.com/developerworks/mydeveloperworks/groups/service/html/communityview?communityUuid=4544bafe-c7a2-455f-9d43-eb866ea60091) for free. IBM HeapAnalyzer has been the Java heap analysis tool of choice for many of IBM engineers and architects all over the world for over a decade.

We are going to utilize the IBM HeapAnalyzer to detect classloader leaks in this article.

First, start your IBM HeapAnalyzer with java launcher with the jar file. For example, <java_path>java -Xmx2g -jar ha443.jar will start IBM HeapAnalyzer version 4.4.3 with 2 GB of Java heap.

IBM HeapAnalyzer
IBM HeapAnalyzer

As soon as you can see above the IBM HeapAnalyzer screen, you can just drag and drop the Java heap dump file to the tool or select File->Open menu to open the Java heap dump. You can also click on the folder icon in the tool bar to bring the Java heap dump into the tool.

Open Java heap dump
Open Java heap dump

If you click on Analysis tab, the IBM HeapAnalyzer will show you a leak suspect after parsing the Java heap dump. About 98.2% of Java heap is used by the LeakClass based on the analysis of the IBM HeapAnalyzer.

Analysis Result from IBM HeapAnalyzer
Analysis Result from IBM HeapAnalyzer

Summary view will show you detailed information about the Java heap dump.

Java heap dump information from IBM HeapAnalyzer
Java heap dump information from IBM HeapAnalyzer

If you click on LeakSuspect tab, you can see only the leak suspect table. Let’s look at each leak suspects by invoking List all entries context menu with right mouse click.

List all entries menu from IBM HeapAnalyzer
List all entries menu from IBM HeapAnalyzer

Now we have all the entries of LeakClass sorted by TotalSize.

Leak suspects from IBM HeapAnalyzer
Leak suspects from IBM HeapAnalyzer

If you are wondering how each LeakClass looks like in the reference tree view, you can invoke Find object in a tree view context menu with right mouse click.

Find object in a tree view menu from IBM HeapAnalyzer
Find object in a tree view menu from IBM HeapAnalyzer

Now we can see its classloader and peer LeakClass objects in a reference tree view.

Tree View from IBM HeapAnalyzer
Tree View from IBM HeapAnalyzer

No Java heap dumps? No problem

Introducing verbose class trace

What if you cannot use Java heap dumps either? You can enable –verbose:class, a Java launcher option. But you probably have to restart your Java virtual machine.

Java launcher provides -verbose:class option to display information about each Java class loaded.

Listing 7. –verbose:class trace
class load: java/lang/Object
class load: java/lang/J9VMInternals
class load: java/io/Serializable
class load: java/lang/reflect/GenericDeclaration
class load: java/lang/reflect/Type
class load: java/lang/reflect/AnnotatedElement
class load: java/lang/Class
class load: java/lang/Cloneable
class load: java/lang/Comparable
class load: java/lang/CharSequence
class load: java/lang/String
class load: java/util/Comparator
class load: java/lang/String$CaseInsensitiveComparator
class load: java/io/ObjectStreamField
class load: java/lang/Class$CacheKey
class load: java/lang/ref/ReferenceQueue
class load: java/lang/ref/Reference
class load: java/lang/ref/PhantomReference
class load: java/lang/ClassLoader
class load: java/security/cert/Certificate
class load: java/lang/ref/SoftReference
…

If you enable the trace, you will find the trace entries in your Java console which might not be the best place to store the trace.

On Unix systems, you can redirect class trace to a file simply with redirection:

java -verbose:class com.ibm.jinwoo.classloader.testcase.LeakTest > verboseclass.log

On Windows™ systems, you can redirect class trace to a file with redirection and duplicate of handles:

java -verbose:class com.ibm.jinwoo.classloader.testcase.LeakTest > verboseclass.log 2>&1

Open verbose:class

If you select File->Open verbose:class/javacore menu item, you can analyze Java verbose class trace.

As soon as the verbose class trace is loaded, suspect class is shown below.

Verbose class trace
Verbose class trace

If you click on the suspect class, you can see the list of containers from which the class is loaded.

Suspect classes
Suspect classes

Let’s select Analysis->Suspect View to get more information about the suspect class. The tool shows that the class is loaded 9,883 times and list of classloaders that loaded the class.

Suspect view
Suspect view

If you select Analysis->Tree View, you can see class/classloader tree representation and the container classloader loaded 9,887 classes.

Tree view
Tree view

Test case II

Do you remember the last time you encountered any java.lang.ClassCastException? We can find out root causes of this problem with verbose class trace and IBM ClassLoader Analyzer. We will generate ClassCastException by casting objects instantiated from a different runtime class. An instance returned from cls.newInstance() is instantiated from a class loaded from the custom class loader, then we will cast it with a class loaded from a different class loader. Even though the two classes have the same binary name, they are different runtime classes since they are loaded from two different class loaders.

Listing 8. TestClassCastException.java
/*
 * Author : Jinwoo Hwang, jinwoo@us.ibm.com
 * TestClassCastException.java
 * (C) Copyright IBM Corp.
 */
package com.ibm.jinwoo.classloader.classcastexception;

import java.net.URL;
import java.net.URLClassLoader;

public class TestClassCastException {

	public static void main(String[] args) 
throws ClassNotFoundException, IllegalAccessException, InstantiationException {
		ClassLoader classLoader = new URLClassLoader
(new URL[]{getContextClassLoaderClassPath()},null);
		Class cls = classLoader.loadClass
("com.ibm.jinwoo.classloader.classcastexception.TestClassCastException");
TestClassCastException instance = 
		(TestClassCastException)cls.newInstance();
	}
	static URL getContextClassLoaderClassPath() {
		return Thread.currentThread().getContextClassLoader().getResource(".");
	}
}

Let’s compile the TestClassCastException.java and execute it.

Listing 9. ClassCastException
Exception in thread "main" java.lang.ClassCastException: 
com.ibm.jinwoo.classloader.classcastexception.TestClassCastException incompatible with 
com.ibm.jinwoo.classloader.classcastexception.TestClassCastException
	at com.ibm.jinwoo.classloader.classcastexception.TestClassCastException.main
   (TestClassCastException.java:15)

You will find that we have java.lang.ClassCastException. We need to enable Java class trace to find out what went wrong with –verbose:class command line option provided by the Java launcher.

On Unix systems, you can redirect class trace to a file simply with redirection:

java -verbose:class com.ibm.jinwoo.classloader.classcastexception.TestClassCastException > classcast.log

On Windows™ systems, you can redirect class trace to a file with redirection and duplicate of handles:

java -verbose:class com.ibm.jinwoo.classloader.classcastexception.TestClassCastException > classcast.log 2>&1

Let’s select File->Open verbose:class/javacore menu item or drag and drop the verbose class trace to the tool. As soon as the verbose class trace is loaded, the tool identifies suspect classes.

Verbose class trace
Verbose class trace

If you click on the suspect class, class containers are listed below. So we have classes loaded from two different containers. A container is where a class is loaded from. It could be a file such as a jar file, a directory or any other resource that a class loader can load a class from.

Here we can see that the TestClassCastException class is loaded from a directory.

Class containers
Class containers

You can select Analysis->Suspect View to list all suspects. We are interested in the classes with multiple containers since those classes are probably loaded multiple times from different class loaders. Fortunately we see only one class with multiple containers but you could expect to see more than that in less than perfect environment.

Suspect view
Suspect view

Let’s select the TestClassCastException class to get detailed information about the class. On the property/value table on the right, we can see the list of containers, the number of times loaded and the name of the class.

List containers
List containers

If you click on one of the containers, it will expand and you can see which classes are loaded from the container.

Verbose class trace: Container view
Verbose class trace: Container view

Let’s take a look at the tree view by selecting Analysis->Tree View menu item.

Tree view menu item
Tree view menu item

Let’s take a look at the tree view. In the tree view, we can see containers and their classes. We have System container from which 427 classes are loaded and a directory from which 2 classes are loaded. The number in the brackets represents number of times classes are loaded.

Tree view of verbose class trace
Tree view of verbose class trace

If you select a container from the tree view, you can see detailed information in the window on the right such as container name, the number of classed loaded from the container and the list of loaded classes. If classes with the same binary name are loaded multiple times, you will see duplicate entries in the loaded classes.

Tree view details of verbose class trace
Tree view details of verbose class trace

So far we were able to diagnose the same problem with different perspectives. Let’s take a time to look around other miscellaneous features of the IBM ClassLoader Analyzer.

How to use Options menu

Under the Options menu, there are User Interface Profiles, Help Contents Browser, Show Console and Clear Console menu items.

Options Menu
Options Menu

User Interface Profile

You can change user interface experience with Options->User Interface Profiles menu item. There are Nimbus, System and Java user interface options.

User Interface Profiles
User Interface Profiles

Help contents browser

You can choose your system’s web browser or the tool’s internal web browser to read the tool’s help contents documents by selecting Options->Help Contents Browser menu item.

Help Contents Browser
Help Contents Browser

How to use Help menu

The Help menu has Help Contents, About and License Agreement menu items.

Help Menu
Help Menu

Help Contents

If you select Help->Help Contents, you can read this document from the tool.

Help Contents
Help Contents

About

You can read basic information about the tool by selecting Help->About menu item.

About IBM ClassAnalzyer
About IBM ClassAnalzyer

License Agreement

You can review the license agreement by selecting Help->License Agreement menu item.

License Agreement
License Agreement

Conclusion

We learned basic concept of class loader, various types of class loaders, class load policies and loading mechanisms on a Java virtual machine and an IBM WebSphere Application Server runtime. We built custom class loaders to generate class/classloader leaks and class cast exceptions. We also diagnosed problems with a variety of artifacts such as Java heap dump, Java class trace and IBM Javacore with IBM ClassLoader Analyzer and IBM HeapAnalyzer.

In summary, Java class/classloader leaks and other class loader related problems such as class cast exceptions can be diagnosed by analyzing IBM Javacore, Java heap dump or Java verbose class trace with IBM ClassLoader Analyzer and IBM HeapAnalyzer.


Download

DescriptionNameSize
Test Files for this tutorialclassloadertestcase.zip10KB

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into SOA and web services on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and web services
ArticleID=948439
ArticleTitle=Diagnosis of Java class loader memory leaks
publish-date=10182013