Question

I'm trying to figure out how class importing works in Java. I have the following file structure:

testProject
    pkgA
        A.java
        A.class
    dir
        pkgB
            B.java
            B.class

The contents of A.java are:

package pkgA;

public class A {
    public static String funcA() {
        return "funcA in class A in pkgA";
    }
}

The contents of B.java are:

package pkgB;

import pkgA.A;

public class B {
    public static void main(String[] args) {
        System.out.println((new A()).funcA());
    }
}

In testProject I run:

javac pkgA/A.java

The above command doesn't print anything.

In testProject/dir I run:

javac pkgB/B.java -classpath ..

The above command doesn't print anything.

In testProject/dir I run:

java pkgB/B -classpath ..

The above command prints the following:

Exception in thread "main" java.lang.NoClassDefFoundError: pkgA/A
    at pkgB.B.main(B.java:7)
Caused by: java.lang.ClassNotFoundException: pkgA.A
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 1 more

What am I doing wrong?

Giving the classpath as an absolute path doesn't help.

$ java -version
java version "1.7.0_51"
OpenJDK Runtime Environment (IcedTea 2.4.4) (7u51-2.4.4-0ubuntu0.12.04.2)
OpenJDK 64-Bit Server VM (build 24.45-b08, mixed mode)

OS is Ubuntu 12.04

Thanks!

Was it helpful?

Solution

Note that your classpath spec must preceed classes or .java files e.g.

java -classpath .. pkgB/B 

(the same applies to the javac invocation).

I would compile everything at the same time e.g.

javac -classpath {whatever} {complete list of .java files}

for consistency's sake.

Specify the compiler output directory to be separate to your source (e.g. a directory called classes). That makes life simpler in terms of managing your code and the compiled artifacts.

Going forward, you should investigate a build tool such as Maven or Ant (or Gradle or Sbt etc.). That will make life much more manageable as you add source files, config or dependencies.

OTHER TIPS

Check your classpath and make sure the current directory(directory that holds pkgA and pkgB) is in the classpath.

It's not always about the class you first see, it's also about what's in them.

1) You have a class called "com.my.Clazs".

2) The class imports "com.my.other.Clazzzz";

3) You have a static method inside Clazs

public static void doFoo() {


       /* The call to Clazs.doFoo() will result in NCDF Error if you
        * skip Clazzzz lookup in classpath.
        *
        */
       Clazzzz anObject = new Clazzzz(); 

}

if you are trying do something from Clazs statically, it will give you NoClassDefFoundError because it cannot load all the dependencies fully to qualify this as a valid class. In other words, all the URLs cannot be resolved fully.

This kind of problem is not unusual even when you have dependency manager e.g. Maven. You might forget that you have a compile-time dependency on certain jars/classes (e.g. Java Tools.jar) which you also need to load when you start the application.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top