Monday, August 27, 2007

Java "class"-ic errors

Few errors are so common (Frequently Faced Errors or FFEs?) - asked many times in forums, email lists (internal/external) - and it is frustating to face one of these "starting problems". I am talking about the classloading errors with Java. I'll try to list few common errors and most probable reasons.

  • Error occurred during initialization of VM
    java/lang/NoClassDefFoundError: java/lang/Object
    Two possible reasons:
    1. You are trying to run 64-bit JVM (SPARCv9 or AMD-64) with -d64 option. But, you did not install 32-bit JVM. Yes, to run 64-bit JVM you have to install a 32-bit JVM and then install 64-bit binary on the same directory
    2. You are playing with -Xbootclasspath option (why? - in most scenarios it is wrong!) and you didn't include rt.jar in boot class path

  • Exception in thread "main" java.lang.UnsupportedClassVersionError: Bad version number in .class file
    Unsupported major.minor version 49.0
    Reason: You are trying to run a class compiled with newer version of JDK. For example, you have compiled the class with JDK 5.0 and try to run on JDK 1.4.2. Class file major/minor version evolves with major JDK releases. Each JDK version supports only upto a specific class file major.minor version.
    1. Java SE 6 class file version 50.0 or below
    2. JDK 5.0 class file version 49.0 or below
    3. JDK 1.4.2 class file version 48.0 or below
    While you can run a .class file compiled with past release of JDK, the other way around does not work. You can use javac's -target option. Also, always check version of "java" used to run your program by using -version option.

  • Exception in thread "main" java.lang.NoClassDefFoundError: tmp/t (wrong name: t)
    Reason: The class name as in .class file is different from what is specified in command line. In the above error scenario, the .class file has the name "t" (in unnamed global package) but user attempted to load it as "tmp.t" (t in tmp package). You have to check package declaration in your source files and confirm that the files are under proper subdirectories (use javac's -d option to put .class files under correct subdirectories). Also you may want to check directory, file name case -- remember to do this on case insensitive file systems as well. It is better to use jar files whenever possible (rather than directories)

  • Exception in thread "main" java.lang.NoClassDefFoundError: x
    This is good (bad?) old error! It is better to check
    1. the value of CLASSPATH environment variable
    2. the value passed as -classpath or -cp option
    3. check that proper path separator (; on Windows, : on Unix - it is easy to miss or use wrong separator for your OS) is used in your classpath specification
    4. Remember that "." (the current directory) is included by default in classpath - but if you have specified CLASSPATH, then that overrides. i.e., With CLASSPATH specified, "." is not automatically added to classpath.
    5. With Mustang (Java SE 6) you can put all your all jar files in one or fewer directories and use classpath wildcards to avoid typos in jar file names.
    6. When in doubt, check again before posting to forums :-) Yes, typos are quite common :-)
When you are out of starting troubles, you may still face other classloading issues. "unexpected" class is loaded etc. How can you debug that?
  • Turn on -verbose:class. This prints debug info on each class load. The source of the class file loaded (rt.jar , foo.jar) is also printed along that.
  • Check your configuration. There are many ways to pass arguments to running JVM. (command line argument, environment variables, config files of app/web servers). You may want to check what actual arguments were "seen" by the JVM. You can check these using
    1. jps
    2. jinfo
    The value of the System property java.class.path is the application classpath used. Similarly, the value of the System property sun.boot.class.path is value of bootstrap class path (Sun specific).

Share |

No comments yet


Embed Wave to Blogger