3.21.2008

A Pesky Java Error: NoClassDefFoundError

I've been studying Java through a couple of excellent books, one of them being Thinking in Java (3rd Edition) by Bruce Eckel.

Eckel introduced his own unit testing classes in his sample code. He called the automated testing "SimpleTest". My problem was that the sample Java applications could not find the SimpleTest classes, no matter how hard I tried to configure my environment.

Here was the error I kept getting at run time:

Exception in thread "main" java.lang.NoClassDefFoundError


Solution:
The final solution turned out to be in Eckel's documentation all along, at http://mindview.net/Books/TIJ/. Here's what he said:

Set your CLASSPATH variable to include "." (the current directory) and the code directory.

I had already set my CLASSPATH to include the code directory, but I somehow missed the one about the dot "." so after I tried adding "." in the CLASSPATH and it worked! (For instructions, see below).

Additional information:

To work around the problem, I commented out all references to SimpleTest. And this allowed me to compile and run the sample code. But then I started aiming for test-driven programming, which made me more interested at making SimpleTest work. I read and re-read Eckel's documentation until I finally noticed the instructions about adding the "." to CLASSPATH.

How to set CLASSPATH in Mac OS X

Use a text editor like TextWrangler, which can open hidden files. Navigate to your home directory "~/"and look for a file called .bash_profile. If none, create the file and save it with that file name (no extensions). The file should contain the following line:

export CLASSPATH="/Users/myhome/Development/tij/:."

Explanation:
  • "/Users/myhome/Development/tij" is where my Thinking in Java sample code is saved.
  • The colon ":" is the separator. You can add additional CLASSPATH variables by separating them with a colon.
  • Note the dot "." after the semicolon. This is what I kept missing as I read and reread Eckel's documentation. After I added the dot, everything worked!
Alternatives to changing CLASSPATH in bash

Other programmers advise that it's better to just set the CLASSPATH from the command line, eg, by invoking:
java -classpath
However, this is also tricky, so I prefer to set my CLASSPATH from the environment variables of Mac OS X.

Links:

1 comment:

  1. While it's quite flexible to set the classpath from the cmd-line, via -cp parameter, it's also a pain in the ass once your classpath starts growing. I've tended to just set up a launcher shell script for my programs, so that the classpath is set up, but allows me to have specific locations and libraries for different programs. However, in your case, where you're just dealing with a few libraries, using the cmd-line parameter might be good enough. Or just export the environment variable in your .profile.

    Note: Java 6 allows you to use wildcards when specifying libraries in a classpath, so you can have a setup where you just use one directory to contain your libraries, eg. /home/myuser/java/lib, and then specify it as such: java -cp /home/mysuser/java/lib/*.jar - this picks up ALL the jar files in that directory, whereas in earlier Java versions you had to specify each bloody library.

    Sadly, JDK6 is still unreleased for OS X! Only developer preview - Intel only - is available. Apple have been absolutely terrible on this issue lately.

    ReplyDelete

Thank you for commenting! Your comment will be submitted for review and approval. Please return soon!