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
You need the Hello.jar on the classpath when you run as well as when you compile.
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
!!!
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).
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
You need to include the Hello.jar file in the classpath when you launch it too.
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
Related
I have a java gradle projectA that references another java gradle projectB, that builds as a lib.
My gradle build configuration seems to be fine, since I can import and use classes from the other project, and it compiles. But when I try to run the application from the command line I get an error...
Exception in thread "main" java.lang.NoClassDefFoundError:
dawcore/SamplerInstrument at DawCLI.main(DawCLI.java:17) Caused by:
java.lang.ClassNotFoundException: dawcore.SamplerInstrument at
java.net.URLClassLoader.findClass(URLClassLoader.java:382) at
java.lang.ClassLoader.loadClass(ClassLoader.java:424) at
sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) at
java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 1 more
It seems to be complaining that it can't load the classes in the jar at runtime....which makes sense. But I don't know how to have it successfully load those classes.
my current run command that does not reference the jar, is as follows....
/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/bin/java -ea -cp "build/classes/main/" DawCLI
Running this gives the initially mentioned error.
I then read the docs on java -cp argument. It says to provide additional classpath directories, to separate them by semicolon.
I susequently updated my run command to be as follows....
/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/bin/java -ea -cp "build/classes/main/;../DawCore/build/libs/DawCore.jar" DawCLI
This gives me the following error....
Error: Could not find or load main class DawCLI
My main function is as follows..
import dawcore.*;
public class DawCLI {
public static void main (String [] args) throws IOException {
SamplerInstrument samplerkick = new SamplerInstrument();
}
}
According to the docs I seem to be doing this correctly, but am still getting errors. Any insight on this would be greatly appreciated!
Thanks
The solution was to replace the delimiting semi-colon with a colon instead. Even though the first line of the javadocs on -cp command indicate that you should use a semi-colon.
This could be because I am running on linux and those docs indicate Windows.
https://docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html
public class RunScript {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
I created a Java project and a package called com.klong
Inside of the package I have one .java file with the above code in it.
I export it into a runnable jar file. Then I try to run the jar in a command line using this:
java test.jar
When I try that, I get the following error
C:\Users\IBM_ADMIN\Tracing stuff>java test.jar
Exception in thread "main" java.lang.NoClassDefFoundError: test.jar
Caused by: java.lang.ClassNotFoundException: test.jar
at java.net.URLClassLoader.findClass(URLClassLoader.java:434)
at java.lang.ClassLoader.loadClass(ClassLoader.java:653)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:358)
at java.lang.ClassLoader.loadClass(ClassLoader.java:619)
Could not find the main class: test.jar. Program will exit.
I've tinkered with exporting into a normal jar file and such. I've looked at other questions about this error. I've tried using commands such as set classpath=BLEH
This project is as simple as can be so hopefully you can help me figure out this pesky error!
You need to run java -jar test.jar, what you're currently doing is asking java to look for compiled classes with the name test.jar.
I am having two problems regarding compiling and running an Eclipse java project from command line. This works fine when I am just running from the eclipse IDE. I tried googling but couldn't really get the thing working. Any help is much appreciated.
Problem 1: When I try to compile from a location different from the directory where the .java file is, it throws the error "cannot read: myfile.java". But if I migrate to this directory then it compiles.
The command that I was giving is (when in some other directory):
javac -cp C:\ABC\src\XYZ myfile.java
The command that I was giving when in XYZ directory:
javac myfile.java
This generated two .class files myfile.class and Testing_Thread.class(I guess this because I have a thread in my code)
Problem 2: After I have compiled by going to its directory, when I try to run the program, I get the error "Exception in thread "main" java.lang.NoClassDefFoundError: myfile (wrong name: XYZ/myfile.java)" even when I am trying to run from the XYZ directory. I get the same error when I try to run from some other place also.
The command that I was giving when in XYZ directory:
java myfile
The command that I was giving when in some other place:
java -cp C:\ABC\src\XYZ myfile
I am also attaching a hierarchy of my directory structure if it is of any help:
These examples assume the following source structure:
C:\temp\compile-test\src\a\b\c\D.java
Where D.java is:
package a.b.c;
public class D { }
The first problem, cannot read: myfile.java, is because it is not correct to use the cp command line option to point to your source code.
C:\temp\compile-test\src>javac -cp c:\temp\compile-test\src\a\b\c D.java
javac: file not found: D.java
Usage: javac <options> <source files>
use -help for a list of possible options
This should instead be the following, where javac is run from your source folder, and we can use relative paths to the source files (NOTE - javac is run from the source folder here):
C:\temp\compile-test\src>javac a\b\c\D.java
Or this, where we specify full paths to the source files, and javac can be run from anywhere (NOTE - javac is run from C:\ here):
C:\>javac temp\compile-test\src\a\b\c\D.java
Both of the above options will result in your class files being created in the same folder as the source. I.e.:
C:\temp\compile-test\src\a\b\c\D.class
For the second problem, if you try and run a class that has a package name from 'inside' the package, this will result in the name being wrong (NOTE - java being run from 'inside' the package here):
C:\temp\compile-test\src\a\b\c>java D
Exception in thread "main" java.lang.NoClassDefFoundError: D (wrong name: a/b/c/D)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
Could not find the main class: D. Program will exit.
To run the D class, you should be at the package 'root', and supply the Fully Qualified Class Name. I.e.:
C:\temp\compile-test\src>java a.b.c.D
Exception in thread "main" java.lang.NoSuchMethodError: main
Note I get an exception as the D class doesn't have a main method, and so cannot be run. To fix, we add a main method:
package a.b.c;
public class D {
public static void main(String[] args) {
System.out.println("main");
}
}
and re-run:
C:\temp\compile-test\src>java a.b.c.D
main
I found a couple other questions with my problem, but the solutions did not work. I have a web page on my local server that you can input text for a whole java class. When submit is clicked I want the output to be displayed. Using shell_exec I can compile the java file. I get nothing when I try to run it, though.
shell_exec("javac /folder/Test.java"); // works
echo shell_exec("/usr/bin/java folder.Test"); // nothing is returned
I decided to use the full path to java when I read that it solved the problem for someone else. When I run:
/usr/bin/java folder.Test
from the command line it works.
The Test.java file looks like this:
package folder;
public class Test{
public static void main(String[] args){
System.out.println("testing");
}
}
EDIT: I could not get w0rldart's to work. I can actually see something when I try Mathieu's. I tried adding the -classpath option (I am not sure if I am using it correctly)
echo shell_exec("java -classpath ./folder/ Test 2>&1");
I get the same error as without -classpath:
Exception in thread "main" java.lang.NoClassDefFoundError: Test Caused by:
java.lang.ClassNotFoundException: Test 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:321) at
sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294) at
java.lang.ClassLoader.loadClass(ClassLoader.java:266) Could not find the main class:
Test. Program will exit.
IT WORKS:
Just had to remove the period from
echo shell_exec("java -classpath ./folder/ Test 2>&1"); //error
echo shell_exec("java -classpath /folder/ Test 2>&1"); //works
I'm very uncertain this will make a difference. But just to be sure, have you tried adding 2>&1 after your command?
echo shell_exec("/usr/bin/java folder.Test 2>&1");
I don't think system.out.println is using stderr to display its output, but it might be worth trying anyway...
If you want to use Test class from folder package then Test.class needs to be saved in a folder named folder. Then you need to have folder's parent directory on the CLASSPATH.
So if your configuration is the following: /rootdir/foo/folder/Test.class then you can start Test like this: java -classpath /rootdir/foo folder.Test.
I think this behavior is the same if you use java from php's shell_exec.
I'm trying to understand how jars and packages work in Java. So to do this, I created a simple test JAR and am trying to use a class contained in that jar. Simple enough, but it is giving me errors like "class not found". Here's the setup:
1) I have a file called MyHelloWorld.java, which will be packaged in a JAR:
package com.mytest;
public class MyHelloWorld {
public String getHello() {
return "Hello";
}
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
2) I have another file called 'HelloHello.java' which uses the function getHello() in com.mytest.MyHelloWorld
import com.mytest.*;
public class HelloHello {
public static void main (String[] args) {
MyHelloWorld hello = new MyHelloWorld();
System.out.println(hello.getHello());
}
}
3) To package the MyHelloWorld class inside a JAR, I created the folders com/mytest in the current directory, and moved MyHelloWorld.java to that folder
4) I compiled MyHelloWorld.java in that folder using javac MyHelloWorld.java
5) I ran jar -cf myhello.jar ./com/mytest/*.class from the root folder to create the JAR file (as described in http://www.javacoffeebreak.com/faq/faq0028.html)
6) I copied HelloHello.java and myhello.jar to a new folder with nothing else in it, to test this setup
7) javac -cp ./*.jar HelloHello.java [succeeds]
8) java -cp ./*.jar HelloHello [FAILS] (I also tried just `java HelloWorld', which failed too, with a different error message)
This last statement fails with the message:
$java -cp ./*.jar HelloHello
Exception in thread "main" java.lang.NoClassDefFoundError: HelloHello
Caused by: java.lang.ClassNotFoundException: HelloHello
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:315)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:330)
at java.lang.ClassLoader.loadClass(ClassLoader.java:250)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:398)
Any idea why it's failing? Any insights you can provide on why it works this way, and how package names are defined inside a JAR etc. would also be appreciated!
I believe it is looking in the jar for your HelloHello class. You probably need the current folder on the classpath too.
java -cp .:myhello.jar HelloHello
You should use:
java -cp .:./* HelloHello
java and javac treat -cp argument a bit differently. With java the * in cp will automatically load all the jars it finds in the given location.
Also, the colon : is the separator between different classpath elements.
Make sure if HelloHello.class is in appropriate directories structure (com/mytest) than change your 8th step:
8) java com.mytest.HelloHello //or java -cp .;*.jar com.mytest.HelloHello
well, java HelloHello works too