Introduction

Every developer who has used Java is familiar with the classpath. Usually it doesn't take long to generate your first ClassNotFoundException or NoClassDefFoundError.

The rules for for classloading are well documented and easily understood. For example if your classpath reads C:\lib\jar1.jar;C:\lib\jar2.jar;C:\lib\jar3.jar most developers will tell you that first the classloader will search jar1 for classes, followed by jar2 and jar3. If you ask them what would happen if the same class is located in jar1 and jar2, most should realize that only the version located in jar1 will get loaded. The situation is complicated slightly with container based classloadering where hierarchies of classloaders are used, but even then the rules are usually well documented.

It's not the understanding that makes tracking down classpath errors difficult, it's the volume of the task.

Have you ever added a class to the classpath but weren't sure if it was being obscured by another version elsewhere on the classpath?

Have you ever added jar and wondered what other jars are needed for that jar to function properly? In other words what jars is this jar dependent on?

Have you ever looked at the jars on a project and wondered if all of them are still needed, or just remain as some historical artifact?

Have you ever run a J2EE application in a container and found your application just not running and suspected that the container has introduced an incompatible version of an XML parser?

All of these issues are well known situations with Java and until now the tedium of looking jar by jar was the only way to resolve them. Classpath Helper provides a simple visual way of quickly seeing all of these issues.

How it Works

The core of Classpath Helper is a classloader that does more than just loading classes into the JVM. Classpath Helper not only records the exact location where a class is loaded, it also searches the classpath in proper order (including hierarchies of classloaders) looking for other locations for that same class. It verifies the bytes to determine if the class bytes from blocked classes are the same or different.

Classpath Helper also reads the byte code directly searching its class definition for dependencies on other classes. A reference to a class not found on the classpath would normally cause a ClassLoader to fail with the well known ClassNotFoundException or NoClassDefFoundError, but Classpath helper is able to bypass these limitations with its independent reading of the byte code. This allows Classpath Helper to merely report on missing class references instead of running into errors. A class that can not find its dependent classes cannot be properly loaded into the VM.

Showing you the information

Classpath Helper provides easy views in Eclipse for quickly processing this information to help you resolve errors.

Class Path View

The basic Class Path View breaks down the information in the very familiar form of jar/folder locations with classes inside of them. This flattened view even shows the correct order when loading via a hierarchy of class loaders. The various icon decorations make it easy to spot potential issues.

A Detailed description of this view is located in Getting Started

Location by Location View

The Location by Location View provides a higher level of abstraction when showing the class related information. Instead of drilling down immediately to the class level. Location by Location shows dependencies and references at the jar level. It even shows all the unresolved classes for an entire jar.

A Detailed description of this view is located in Getting Started

Packages View

The Packages View organizes the class path information around the notion of Java packages. This is useful in cases where the location is not known or not important.

A Detailed description of this view is located in Getting Started

Not on Classpath View

The Not on Classpath View provides a quick way of scanning jars in the current project that are not on the classpath. This is useful when building up an Eclipse project and a large number of legacy jars exist that you might not need. So preferably you can scan for classes you know you need and only add the jars you still use.

A Detailed description of this view is located in Getting Started

Note Regarding Eclipse

Eclipse by default initializes with a very small JVM stack size. It is important to configure Eclipse to run with a larger stack size. This can be accomplished via the -Xmx attribute applied to the eclipse commandline. Failure to do so will lead to out of memory errors in Eclipse.

  eclipse.exe -Xmx64m

Extensibility

Classpath Helper was designed with extensiblity in mind. By providing a highly configurable ClassLoader as the base data model, it's possible to simulate the class loading of nearly any class loading environment such as J2EE servlet or application container. Classpath Helper makes writing your own ClassLoader model easy and even supplies a tutorial.

Limitations

Although reading the Java byte code provides comprehensive access to the dependencies between Java classes, there are two notable areas that cannot be inferred from the byte code.

Condition Description
Dynamic loading via Class.forName(java.lang.String); Because the String values supplied to Class.forName() can come from anywhere (often a configuration file) it is impossible to, in general, determine their values. As a result many common dependencies, such as J2EE servlet and EJB descriptors, cannot be inferred via the byte code.
static final constants In Java it is common to define constants in an Interface that is referred to in other classes. For performance reasons Java compilers inline java.lang.XXX constants. This means that no reference back to the originating Interface exists within the byte code of classes that refer to it. In otherwords, despite a compile time dependency on constants from an Interface, Java compilers eliminate runtime dependencies on constants Interfaces, leaving no trace in the byte code.

SourceForge.net Logo