|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 6 of 6
Listing 6.2 TopLevel.java
package com.javaworld.jpitfalls.article2;
public class TopLevel
{
static SuperFrame frame;
public static void main(String args[])
{
frame = new SuperFrame();
}
}
Under JDK 1.1.8, attempting to run TopLevel using a classpath configured for JDK 1.2 produces:
E:\classes\com\javaworld\jpitfalls\article2>java
com.javaworld.jpitfalls.article2.TopLevel
java.lang.NoClassDefFoundError: com/javaworld/jpitfalls/article2/SuperFrame
at com.javaworld.jpitfalls.article2.TopLevel.main(Compiled Code)
The error states that the JVM cannot find the class SuperFrame.class; however, the directory shows that the class is in the same package and the same directory as TopLevel.class. So the class is clearly present. If the JVM can find TopLevel.class, why can't it find SuperFrame.class? They are in the same package and the same directory!
When I tried to run the SuperFrame class directly, I received:
E:\classes\com\javaworld\jpitfalls\article2>java com.javaworld.jpitfalls.article 2.SuperFrame Can't find class com/javaworld/jpitfalls/article2/SuperFrame
Still no help. The code for SuperFrame.java is found in Listing 6.3; it merely extends a JFrame and is only used to illustrate the behavior.
Listing 6.3 SuperFrame.java
package com.javaworld.jpitfalls.article2;
import com.sun.java.swing.JFrame;
public class SuperFrame extends JFrame
{
}
To solve the problem, I wrote a simple command line utility to load a class and catch any thrown errors. My hope was that
the error-reporting would be more detailed. Listing 6.4 presents the LoadClass class.
Listing 6.4 LoadClass.java
import java.util.*;
public class LoadClass
{
public static void main(String args[])
{
if (args.length < 1)
{
System.out.println("USAGE: java GOV.dia.mditds.util.LoadClass
fullClassName");
System.exit(1);
}
try
{
Class c = Class.forName(args[0]);
if (c != null)
System.out.println("Class: " + c.getName() + " loaded
successfully.");
else
System.out.println("Unable to load: " + args[0]);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
When I ran the utility program LoadClass to load the class in question, I received:
E:\classes\com\javaworld\jpitfalls\article2>java LoadClass
com.javaworld.jpitfals.article2.SuperFrame
java.lang.NoClassDefFoundError: com/sun/java/swing/JFrame
at LoadClass.main(LoadClass.java:15)
That cleared up the error. The JVM incorrectly reported that it could not find a class; actually, it could not fully load
the class because the class depended on a class that could not be loaded. In that simple example, the SuperFrame class wants a Swing class that is not in the classpath. While this has been fixed in Java 1.2, it is important to point out
for the many people still developing programs in JDK 1.1.8. In Java 1.2, the JVM will accurately report the class it cannot
find, instead of reporting that it cannot find the parent class. The LoadClass utility can help you determine why the JVM cannot load a class in Java 1.1.8.
The key to avoiding these two pitfalls is to be careful in your assumptions. The URLConnection class resembles the Socket class in some ways, but their methods will not behave in the same way. As you learned in Pitfall 5, getInputStream() produces adverse side effects in the URLConnection class. Therefore, when posting to a URL, you must observe the proper sequence or you will fall into a trap. Also, don't assume
that your JVM is using the classpath set in the environment variable. Doing so might cause a NoClassDefFoundError. Find out what the JVM understands the classpath to be by using the command line utility in Listing 6.1. To compound the
problem, JVM 1.1.8 poorly conveys this type of error. To receive more detailed reports of your errors, use LoadClass.java in Listing 6.4 to get around the NoClassDefFoundError pitfall. Avoiding these traps will save you and your team hours of wasted time.