| More
Java Paths and Related Exceptions/Errors
 


Java Paths and Related Exceptions/Errors

by Jim White (Director of Training and Java Instructor) ? white@intertech.com

This week?s blog entry is meant to help those just getting into Java development with a couple of very common errors/exceptions they often see when developing Java applications.  However, while my blog entry is aimed at the beginner, I would have to say that of all the questions I receive whenever I have an article published or when I post a blog entry about some API, it seems that at least 1 in 10 will relate back to the topic which I address here.  So perhaps, while the Java classpath, sourcepath, build path and exceptions that occur from improper settings is fundamental to Java development, it may be more than just a ?beginners? issue.

Paths

First off, what are Java classpath, sourcepath, and build path?  Maybe, to back up a bit, what the heck is a path?  In computer operating systems, a path is the route through a file system to some file.  So, if your friend were to ask you to get a file off of some server, you might ask him or her ?what path is it on??   In other words, you would be asking, where do I find that file on the server?s file system.

Well, the classpath, sourcepath and build path also describe a path through the file system.  These ?paths? are used by the Java compiler and Java virtual machine.  The sourcepath tells the Java compiler where Java source code files can be found.  That is, it informs the Java compiler where to find .java files.  The sourcepath is a delimited set of file system directories, JAR files or ZIP files (that contain .java definitions).  The delimiter can be different with different operating systems, but on a Windows box, the delimiter is a semicolon (;).

The classpath tells the Java compiler and Java virtual machine (JVM) where Java class and interface files are located.  That is, it informs the Java compiler and/or JVM where to find .class files.  Like the sourcepath, the classpath is a delimited set of file system directories, JAR files or ZIP files (that contain .class definitions).

Perhaps the most difficult of the Java ?paths? to understand is the build path.  The Java build path is the classpath used for building, or in other words compiling, a Java project (a whole collection of Java source files).  The reason build path is a bit confusing is that build path is just a nickname used for classpath in the context of compiling (or ?building?) a project.  In fact, in the command line tools for compiling and running Java applications (javac.exe and java.exe) there is no explicit ?build path? option.  It is just understood that the term ?build path? is the classpath used when compiling (javac).  So build path = compiler classpath.

You might have noticed that classpath is an optional parameter that can be used on both the compiler (javac.exe) and JVM (java.exe).

javac ?classpath .\myclasses;.\libs\foo.jar;.\libs\tools.jar

java ?classpath .\myclasses;.\libs\foo.jar;.\libs\tools.jar

The classpath defined for the compiler (javac.exe) amounts to the build path.  Some actually refer to the classpath used for the JVM (java.exe) as the Java runtime path.

What leads to some of the confusion that some IDE?s (like Eclipse ? see below) explicitly refer to and let you set the "build path.?  And now you know, they are just explicitly letting you set the classpath for building/compiling your project.

Why so many paths?

So you may be asking ?why so many paths??  The purpose of having a separate sourcepath and classpath is that it often a good idea to keep source files (your .java files) and class files (the compiled .class files) in separate directories ? especially for large projects.  Class files are what will ultimately be deployed to users or servers whereas source code is usually not given out.  Physically separating the two helps to maintain protection of files protected versus files that eventually are shipped.  Further, you may borrow or use class files from third parties, other teams, etc.  You often want to use these .class files in your application, but you don?t want to have to maintain them as your code (in fact, you may find legal restrictions against managing these files as your code).

So why would your build path (or classpath for compiling the project) be different than the classpath for runtime execution?  Well, you may be building and testing an application on your developer desktop, but then, when the application is ready to go, it is deployed to some other box or server.  In this case, your ?build path? will probably point to a different set of files than the classpath that is configured for the JVM on the machine that ultimately runs your code.  Can having a different build path and runtime path this cause issues?  As we like to say in Minnesota - ?oh ya, you betcha.?  See the material on the errors and exceptions below.

Path Rules and Precedence

Now that you know about classpath and sourcepath (and of course build path and runtime path too), you should also know about a few rules with regarding to setting these paths in compiler and runtime environments.

If the sourcepath is not specified, the classpath is searched for source files as well as class files.  In other words, the classpath is your default sourcepath!  Therefore, when the source code and class files are located in the same place (often the case for small projects), you might not see a sourcepath ever referenced.

When a source file is found (via the sourcepath or classpath when a sourcepath is not provided), any class file found on classpath is subject to recompilation.  So, if you have a .class file on the classpath, but a .java file for that class is also on the sourcepath, the compiler will check whether the class file is out of date.  If the class file is out of date, the compiler will recompile and overwrite the class file.  A class file is ?out of date? when the date/time of the class file is older than the date/time of the source file.

If a classpath is not specified, then the classpath is the current directory (where the compiler or JVM is run from).  Interestingly, however, if you specify a classpath, then the current directory will not be included as part of the classpath unless it is explicitly added.  That is why you often see ?.? used as part of the classpath in the call to javac.exe and java.exe (as shown below).

javac ?classpath .;.\myclasses;.\libs\foo.jar;.\libs\tools.jar

java ?classpath .;.\myclasses;.\libs\foo.jar;.\libs\tools.jar

Setting the Classpath and Build Path

So how do you set the classpath, sourcepath, and build path when building Java applications?  That answer depends a bit on your development environment.  There are a number of Java IDEs so I can?t tell you how every tool works, but below are some widely used environments and how to set up paths in each of them.  You see some similarities in each, but they are not exactly alike and they don?t always conform to the names (classpath, sourcepath, build path, runtime path) that were described above.

JDK Command Line Tools

As shown in the examples above, the command line compiler and JVM (javac.exe and java.exe) provided with the JDK have command line options for setting the sourcepath and classpath.  Use ?sourcepath <path> on the javac tool to set the compiler?s sourcepath.

javac ?sourcepath .;.\mysourcecode

Use ?classpath <path> or ?cp <path> to specify the classpath on either the compiler or JVM (java.exe).

java ?classpath .;.\myclasses;.\libs\foo.jar;.\libs\tools.jar

java ?cp .;.\myclasses;.\libs\foo.jar;.\libs\tools.jar

Eclipse (or Eclipse-based IDEs like RAD)

In Eclipse (version 3.x) or other Eclipse-based IDEs, a default build path and classpath can be established for all projects.  This can be accomplished through the IDE?s Preferences.  Select Window from the menu bar in Eclipse and then pick Preferences from the resulting menu.

image

In the Preferences Window that appears, select Build Path under the Java preferences to set the default project build path source folder.

imageIf you note, the next entry in Preferences under Build Path is Classpath variables.  In this window, you can set the default classpath (adding folders, JAR files, etc.) that will be added to all projects classpaths.

image In Eclipse-based IDEs, these global build and classpath settings can be further set at the project level.  Right click on the project in the Package Explorer view and select Properties.

image

A similar Preferences window opens that allows you to configure the build path for the project.

imageWhen you execute a project in Eclipse, a classpath argument can be setup in ?Run Configuration? settings for a project.  Right click on the code you wish to execute in Eclipse and select Run As > Run Configurations? as shown in the HelloWorld example below.

image 

In the Run Configurations window that appears, you will find a Classpath tab that allows you to set the classpath for JVM execution.

image

NetBeans

In NetBeans (version 6.x), paths for source code and class files is set per project.  Right click on any project in NetBeans and select the Properties option from the menu.

imageIn the Project Properties window, you?ll find Sources, Libraries and Run categories that allow you to specify source code folders (sourcepath), libraries to be used in compile and execution (part of the classpath) and a way to directly set the ?classpath argument if you like on project execution.

imageimageimage

ClassNotFoundException & NoClassDefFoundError

So now you have your project set up and you are off and writing/compiling your Java code.  But during execution of your code you have a problem.  Two infamous issues are ClassNotFoundException and NoClassDefFoundError.  These two issues are related, but not the same.

To explain, assume you have some simple Java classes Foo and Bar as shown below.

public class Bar {
    public static void main(String[] args) {
        Foo foo = new Foo();
        System.out.println(foo.getMessage());
    }
}

public class Foo {
    private String message = "hello";
    public String getMessage() {
        return message;
    }
}

What happens if, when you go to run Bar, the Foo.class file is not available?  That is when you get a ClassNotFoundException (as shown below when Foo.class is deleted just before executing Bar.class).

image

ClassNotFoundException is thrown at runtime when the JVM ? specifically the ClassLoader of the JVM, tries to load a class but no definition for the class is found.  Typically, this means that the class is missing from the classpath.  How can this happen.  When moving applications to other runtime environments (for example when deploying code to an application server) certain classes that were in the classpath during testing on your development box are not on the classpath of the application server and ?whamo? ? you get a ClassNotFoundException.

NoClassDefFoundError is often though of as synonymous with ClassNotFoundException, but they are different.  NoClassDefFoundError means that a class was found by the ClassLoader of the JVM, but when it tried to load the class, it ran into an error reading the class definition.  In the example below, I copy Bar.class to Foo.class just before trying to run my application.  Of course, the JVM finds the wrong class contents in the Foo.class file and so it throws a NoClassDefFoundError.

imageThere are several reasons for the NoClassDefFoundError problem and that makes finding the solution for this problem a bit harder to locate.  Perhaps there are two classes in your environment that have the same name and the wrong one was picked up by the ClassLoader.  Typically, you must still trace down all the possible .class files that would satisfy the ClassLoader?s search for the class and try to figure out if there is a conflict and/or if the class file has not been compiled correctly.

To assist with class not found exceptions and no def found errors, you might also want to look at utilities like JarScan and Java Class Finder can help locate class files.  Usually, a good understanding of the Java path variables and how they work can help a seasoned Java developer track down a class issue pretty quickly.

To begin to solve this issue, try to locate the class file on the classpath and see if you can?t recompile class before executing your application again.  It might be that the class file is ?stale? and just needs to be recompiled.

To learn more about Java and how the Java compiler and JVM work, join me for one of Intertech?s Java classes (to explore and sign up for a class see our Java curriculum here).


Posted by: Jim White
Posted on: 1/18/2010 at 2:03 PM
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Add comment




biuquote
  • Comment
  • Preview
Loading