views:

445

answers:

6

Hi All,

I'm trying to use the public methods/classed from a project provided as a jar file (called Hello.jar for instance) wrapped in a package called hello.

package hello;

public class Hello
{

 public static void main(String[] args)
 {
    coucou();
 }

 public static void coucou()
 {
   System.out.println("Hello there");
 }

}

In a separate project called Tool, I want to be able to call the method Hello.coucou() so I wrote something like this:

import hello.*;

public class Tool
{

 public static void main(String[] args)
 {
   System.out.println("main program running");
   Hello.coucou();

 }

}

and I compiled Tool.java with the following command (under linux):

$ javac Tool.java -classpath .:./extern/:

where Hello.jar is located in the folder ./extern

This seems to compile fine but when I launch it (i.e. java Tool), I get this:

main program running
Exception in thread "main" java.lang.NoClassDefFoundError: hello/Hello
    at Tool.main(Tool.java:9)
Caused by: java.lang.ClassNotFoundException: hello.Hello
    at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:323)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:268)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:336)
    ... 1 more

I am new to Java (C/C++ background) and I don't understand what I'm doing wrong. Any ideas?

Cheers David


Edit: I tried adding Hello.jar to the classpath on the command line, but I still get the same error:

$ javac Tool.java -classpath .:./extern/Hello.jar:
$ java Tool -classpath .:./extern/Hello.jar:
main program running
Exception in thread "main" java.lang.NoClassDefFoundError: hello/Hello
    at Tool.main(Tool.java:9)
Caused by: java.lang.ClassNotFoundException: hello.Hello
    at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:323)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:268)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:336)
    ... 1 more
+4  A: 

You need the Hello.jar on the classpath when you run as well as when you compile.

Tom
A: 

You need to include the Hello.jar file in the classpath when you launch it too.

Allain Lalonde
+1  A: 

When you run Java you must add the jar file too (adding the directory path only does not work).

See classpath information.

It should be something like this:

java -classpath /java/MyClasses/myclasses.jar utility.myapp.Cool
Pool
Actually the semi-colon mess things up completely and it should really be a colon. The trick to the problem was to have the -classpath option first, i.e. before Tool.
DavidM
Yes, sorry about that, I somehow ignored the Linux part of the question, but updated the answer to reflect this when I realised.
Pool
A: 

java -cp xxx.jar hello where xxx is the jar you want to have in your classpath, if you want multiple jars then separate them using ;

karl

Karl
+1  A: 

Java uses dynamic late binding, so putting the JAR in the classpath during compilation is only necessary to ensure that your code is using the classes from it correctly, but it does not actually embed them into your code as the linker would in C/C++. Thus, you need to set the classpath also when executing the code.

However, this:

$ javac Tool.java -classpath .:./extern/:

should not work either, since JARs need to be put into the classpath directly, not just the directory they live in:

$ javac Tool.java -classpath .:./extern/Hello.jar

Finally, you are placing your code in the default nameless package. This is OK for fooling around, but will cause problems in the long run (for one thing, you cannot import classes FROM the default package anywhere else).

Michael Borgwardt
+2  A: 

Actually the trick was in the order of the arguments in the command line:

Is the -cp (or -classpath) is set last, then it doesn't work

java Tool -cp .:extern/Hello.jar

It has to be first like:

java -cp .:extern/Hello.jar Tool

!!!

DavidM
Yes. Otherwise the "-cp whatever" is passed to main() as the args array. You need to keep in mind the difference between args to the java runtime and the args to your program.
dsm
Ah yes of course, that makes sense now - thanks for the explanation !
DavidM