We have a java app that needs to use a public class form a JAR file. After much frustration with the main application, we have created a simple repo here to try to figure out what is going on.
The overly simple file that ends up in the JAR file is as follows:
package com.mystuff.helpers;
public class printStuff {
public void showMsg(String msg) {
System.out.println(msg);
}
}
We create the JAR file with this command:
jar cvf MyJavaHelpers.jar com
The folder structure is as follows (the printStuff.java file is in the helpers folder):
A listing of the JAR contents is as follows:
jar tf MyJavaHelpers.jar
META-INF/
META-INF/MANIFEST.MF
com/
com/mystuff/
com/mystuff/helpers/
com/mystuff/helpers/printStuff.java
com/mystuff/helpers/README.md
Finally, the program that we have to use this simple class is as follows:
package com.mystuff.testapp;
import com.mystuff.helpers.*;
// To build the JAR file
// jar cvf MyJavaHelpers.jar com
// To display the contents of the JAR file
// jar tf MyJavaHelpers.jar
public class testDriver {
public static void main(String[] args) {
System.out.println("Starting testDriver");
com.mystuff.helpers.printStuff ps = new com.mystuff.helpers.printStuff();
// testPrintStuff(ps);
// testPrintStuffAgain(ps);
}
/*
private static void testPrintStuffAgain(printStuff ps) {
ps.showMsg("This is a fine kettle of clams");
}
private static void testPrintStuff(printStuff ps) {
ps.showMsg("This is a fine kettle of fish");
}
*/
}
In VS Code (v 1.55.0) We have a Java Project to contain our TestDriver that looks like this:
Finally, the issue is that when we try to run the test driver, we get the message:
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
com.mystuff.helpers.printStuff cannot be resolved to a type
com.mystuff.helpers.printStuff cannot be resolved to a type
at com.mystuff.testapp.testDriver.main(testDriver.java:15)
We have tried the command Clean Java Language Server Workspace which seems to indicate that it works, but we cannot get past this error.
Based on what we have looked at, the JAR file appears to be in the correct place (It is in the lib folder of the main app).
The import com.mystuff,helpers.; line does not show as an error, so it seems to us that it is found, however, the actual import of the printStuff class fails. We have tried the fully qualified class name as well as relying on the import and only using the short name. They both fail.
We have seem some guidance about setting the classpath, but have not been able to find how to do that explicitly in VS Code.
Of course, if we do not have this little helper in a JAR file, but just as a side-by-side in the same project, it works just fine. The issue that started us down this journey is trying to use a public class from a pre-packaged JAR file.
Any and all help is greatly appreciated. Thanks in advance.
Before adding the jar to library, you may run the command java -jar printStuff.jar to test if it could be executed successfully.
The error occurs because the class must be called with its fully qualified name. To be clear, the name of this class is not printStuff, It's com.mystuff.helpers.printStuff, so the right command should be:
Turn to the folder;
Compile .java file: javac com\mystuff\helpers\printStuff.java
Generate .jar: jar cvfe printStuff.jar com.mystuff.helpers.printStuff .\
Then readd it to referenced libraries and see if the error goes away.
Related
I'm trying to learn java, more so as a hobby than anything else, taking a different angle from my usual C# where you actually have namespaces and multiple classes in a file(not ranting or anything). However I don't seem to quite understand how the jar creation process seems to work, at least regarding the "files-input" parameter.
I am well aware that there are build tools like and,maven,etc. I just want to have a better understanding of the entire process that's all.
I'm trying to create a jar out of my 2 classes which are in 2 separate packages.
Here is the folder structure:
tryproject\packageOne\MainApp.class
tryproject\packageTwo\Greeter.class
MainApp.java
package packageOne;
import packageTwo.Greeter;
public class MainApp{
public static void main(String[] args){
Greeter greeter=new Greeter();
greeter.setMessage("Hello World");
greeter.sayHello();
}
}
Greeter.java
package packageTwo;
public class Greeter{
private String whatTosay;
public void setMessage(String whatTosay){
this.whatTosay=whatTosay;
}
public void sayHello(){
System.out.println(whatTosay);
}
}
Here is the command prompt output:
C:\Users\SomeUser>jar cfve tryapp.jar MainApp C:\Users\SomeUser\Desktop\LearningJava\tryproject\packageOne\MainApp.class C:\Users\SomeUser\Desktop\LearningJava\tryproject\packageTwo\Greeter.class
added manifest
adding:Users/SomeUser/Desktop/LearningJava/tryproject/packageOne/MainApp.class(in = 414) (out= 299)(deflated 27%)
adding:Users/SomeUser/Desktop/LearningJava/tryproject/packageTwo/Greeter.class(in = 506) (out= 333)(deflated 34%)
C:\Users\SomeUser>java -jar tryapp.jar
Error: Could not find or load main class MainApp
Caused by: java.lang.ClassNotFoundException: MainApp
I don't really understand why it doesn't find my MainApp class and I'm also curious if it is possible to build the jar this way without a pre-made manifest.
For anyone who stumbles upon this post, the reason of confusion, and the reason this didn't work out for me, is because I didn't take into account the fact that I was creating my jar somewhere else than in the root of a drive so the jar structure would look something like this:
Users\SomeUser\Desktop\LearningJava\tryproject\packageOne\MainApp.class
Users\SomeUser\Desktop\LearningJava\tryproject\packageTwo\Greeter.class
The above is how the jar structure looks like after I created it with the following command:
C:\Users\SomeUser>jar cfve tryapp.jar MainApp C:\Users\SomeUser\Desktop\LearningJava\tryproject\packageOne\MainApp.class C:\Users\SomeUser\Desktop\LearningJava\tryproject\packageTwo\Greeter.class
Now in order to run this jar you have to change the above command so that instead of having just MainApp there you have to put the entire project structure like this:
C:\Users\SomeUser>jar cfve tryapp.jar Users.SomeUser.Desktop.LearningJava.tryproject.packageOne.MainApp C:\Users\SomeUser\Desktop\LearningJava\tryproject\packageOne\MainApp.class C:\Users\SomeUser\Desktop\LearningJava\tryproject\packageTwo\Greeter.class
And also you have to modify the package of each .java class file to resemble the structure I just modified in the command. So instead of having just package packageOne; or package packageTwo; you need to rewrite them like this package Users.SomeUser.Desktop.LearningJava.tryproject.packageOne; and package Users.SomeUser.Desktop.LearningJava.tryproject.packageTwo;. The same goes for import.
Now if you modified all your .java files and recompiled them you should be able to run the jar using the command instruction that I mentioned earlier.
But a better solutions, and an easier one is like #Prashant Gupta mentioned above.
For instance just use:
jar cfve tryapp.jar packageOne.MainApp -C C:\Users\SomeUser\Desktop\LearningJava\tryproject\ .
But it will get all the files in that directory so maybe just have a separate directory for binary files or all file you need for your application and another for the source files.
My java class files run in Eclipse but not in command line. I have tried all possible solutions. My code has the following structure:
Client_1/src/filedownload/Client.java
RMI_interface/src/filedownload/Hello.java
The Client.java file is dependent on Hello.java. filedownload is the name of package.
When I compile using the following command, it works.
javac RMI_interface/src/filedownload/Hello.java Client_1/src/filedownload/Client.java
But when I execute the class file in the Client_1/src folder using following command, it does not work.
java filedownload.Client
The error displayed is
Could not find or load main class
I have tried many posts on stackoverflow but I am unable to solve it. I am using ubuntu.
The code structure is
package filedownload;
import ....
public class Client implements Hello, Runnable{
...other functions.....
public static void main(String args[])throws Exception{
}
}
Does your Client class have the main() method ? Where are the .class files after compilation (that is, what's the current directory you're executing the compile from) ? What's the current directory when you try to execute ? What's the classpath when you try to execute ?
Without all that info, there's little chance of anyone being able to get you going (but for the obvious advice of just setting up eclipse and doing everything from within eclipse - letting eclipse take care of all the nitty gritty detail).
(And the questions themselves suggest various possible points of failure in your scenario so look at it.)
All your steps seems to be correct. You didn't share the Client.java code which has main method.
Make sure you follow this main method syntax:
public static void main(String[] args){
...
}
E.g. if you write main without args, it can't be found.
You need to put your classes in a separate folder, separated from your sources.
javac -d bin RMI_interface/src/filedownload/Hello.java Client_1/src/filedownload/Client.java
(folder 'bin' must exist already)
And inside folder 'bin' execute command:
java filedownload.Client
For some reason, I can't get java to run my program. Whenever I try I get the message
"Error: Could not find or load main class Project"
In Command Prompt I type cd Documents since the file is in my Documents folder, type
javac Project.java
then
java Project
to try and run it but I get the above error message.
import java.util.Scanner;
import java.text.DecimalFormat;
public class Project
{
public static void main(String[] args)
{
Code and stuff
}
}
There's a fair bit of code that I left out but I think this is the part that's messed up. Let me know if you need to see the rest of the code and I'll edit this.
Change
java Project
to (assuming Project.class is in your current folder)
java -cp . Project
as it is, you aren't setting a class-path.
You have add the path of .class files in classpath during execution
Run following command:
java -classpath C:\Users\DELL\Documents Project
I am importing one class(it is not there in the default jvm) from one jar package and using it in another package. like I have a class program1.class in package package1 and I am importing this class from another programme program2 in package package2.
package package1;
public class Program1
{
public String sayHello()
{
return "Hello world";
}
}
and importing this class in
package package2;
import package1.Program1;
public class Program2
{
public static void main(String args[])
{
System.out.println("I am in programme2");
System.out.println("I am in programme 1"+new Program1().sayHello());
}
}
I have compiled the program1 and packaged it by
javac -d . Program1.java
jar cf Pack1.jar package1
and second programme by
javac -d . Program2.java
jar cfm Pack2.jar Manifest.txt package2
my manifest file is
Main-Class: package2.Program2
now I am running the programme as
java -classpath path/to/Pack1.jar -jar Pack2.jar
it is giving me error as:
I am in Program2
No class def found error Package1/Program1
If I am running it by specifying the Class as
java -classpath path/to/Pack1.jar;path/to/Pack2(UnJar'ed) Pack2.program2
it is working which is very strange
Means there is a different between specifying the class file containing the main and specifying the jar file of the program.
I have already made sure that I have set Main-Class is set correctly in Manifest.mf, moreover the classpath for pack2 is also specified
So why this error
When you use the -jar option, all other classpath options are ignored. Thats why you are getting a NoClassDefFoundException.
See link here.
Here is the relevant note from that link --
-jar Execute a program encapsulated in a JAR file. The first argument is the name of a JAR file instead of a startup class name. In order for this option to work, the manifest of the JAR file must contain a line of the form Main-Class: classname. Here, classname identifies the class having the public static void main(String[] args) method that serves as your application's starting point.
See the Jar tool reference page and the Jar trail of the Java Tutorial for information about working with Jar files and Jar-file manifests. When you use this option, the JAR file is the source of all user classes, and other user class path settings are ignored.
The fix would be to include the Class-Path in your jar manifest.
I have written two simple Java classes (one of them containing "main()", and the other called by "main()").
Class #1 (containing "main()"):
package daniel347x.outerjar;
import daniel347x.innerjar.Funky;
public class App
{
public static void main( String[] args )
{
Funky.foo();
}
}
Class #2 (called by "main()"):
package daniel347x.innerjar;
public class Funky
{
public static void foo()
{
System.out.println( "Funky!" );
}
}
The above classes appear in different project root folders, and use Maven as the build system (each project has its own POM). The pom.xml file for the main project includes the proper entry to add daniel347x.outerjar.App as the main class, and it properly includes the dependency on daniel347x.innerjar. Both projects build successfully into JAR files.
I use NetBeans to wrap these as Maven projects (in fact, I used NetBeans to create both projects). When I run the main project from within NetBeans, it runs successfully and I see Funky! as the output.
However, when I attempt to run the main class straight from the Windows command line (cmd.exe), passing the JAR file containing Funky on the command line's classpath, as such:
java -classpath "P:\_Dan\work\JavaProjects\JarFuckup\innerjar\target\innerjar-1.0-SNAPSHOT.jar" -jar "P:\_Dan\work\JavaProjects\JarFuckup\outerjar\target\outerjar-1.0-SNAPSHOT.jar"
... I receive the dreaded NoClassDefFoundError:
Exception in thread "main" java.lang.NoClassDefFoundError: daniel347x/innerjar/Funky
at daniel347x.outerjar.App.main(App.java:7)
I have carefully confirmed that, inside the innerjar JAR file noted above containing Funky, that the path structure is daniel347x\innerjar and that inside the innerjar folder is the Funky.class file - and this file looks correct within a HEX editor where I can see the ASCII strings representing the name of the class.
The fact that the class can't be found defies my understanding of Java, which I thought allows you to pass JAR files as a -classpath parameter and it will be able to find classes inside those JAR files.
This very basic point has me flummoxed - an answer that explains what I am doing wrong would be greatly appreciated.
The classpath is ignored when using the -jar option. A way to run your app would be java -classpath "P:\_Dan\work\JavaProjects\JarFuckup\innerjar\target\innerjar-1.0-SNAPSHOT.jar";"P:\_Dan\work\JavaProjects\JarFuckup\outerjar\target\outerjar-1.0-SNAPSHOT.jar" daniel347x.outerjar.App
Perhaps a better approach would be to add a manifest file to the Jar that specifies the class path of the dependent Jars by relative paths. Then..
java -jar "P:\_Dan\...\outerjar-1.0-SNAPSHOT.jar"
..should do it.
Double clicking the main Jar will also launch it. That is mostly useful for GUIs.