Let's say I have the following "project" structure.
*Root/
- manifest.txt
+ com/
+ mypackage/
+ example/
- MyClass.java
- MyClass.class
I know from the docs.oracle.com documentation that the manifest file must be written in the UTF-8 character set and that there must be a space after each colon, and a carriage return ('\r') or a new line ('\n') before save file.
/* ** MANIFEST.TXT ** */
Manifest-Version: 1.0
Class-Path: .
Main-Class: com.mypackage.example.MyClass
/* ** END OF MANIFEST ** */
Creating an executable .jar file using cmd from the root directory.
CMD:
jar -cvfm out.jar manifest.txt com/mypackage/example/*.class
OUTPUT from CMD:
added manifest
adding: com/mypackage/example/MyClass.class(in = 648) (out= 445)(deflated 31%)
Now I'm trying to run the newly created jar file from the root directory:
java -jar out.jar
OUTPUT from CMD:
Error: Could not find or load main class com.mypackage.example.MyClass
I can't get to the goal despite the last problem. What am I doing wrong??? Thank You.
Here is a screenshot of the screen and cmd.:
As you described it, you will get a running jar, and therefore, what you described is not an accurate representation of what you did.
A few steps to check:
Did you paste the complete error message? For example, maybe the error message includes the note Caused by: java.lang.NoClassDefFoundError: MyClass (wrong name: com/mypackage/MyClass) or something along that vein. Then the problem is: Your MyClass.java needs to start with package com.mypackage.example;, it needs to contain class MyClass with that exact casing, and it needs to be called MyClass.java with that exact casing.
Did you actually do all the steps exactly as you laid out in your question? I did, and it works fine. This isn't one of those 'works on one machine and may not work on another' kind of scenarios, which is why I conclude you didn't. For example, if you include just MyClass.class and not com/mypackage/example/MyClass.class (i.e. you run the jar command from something that isn't the directory containing the com directory), you'd get this problem.
NB: 99% of folks building java jars use a build system to do so, such as maven or gradle.
Class-Path: com.mypackage.examples
Main-Class:My class
On Unix don't forget to set the .jar executable permission.
And alternate with no manifest.
Java -cp thejar.jar com.mypackage.examples
Don't forget the main class must have a
public static void main(String args[])
method to start the class.
Related
To put it simply, I have a different error where Eclipse won't allow me to export the recent version of a JAR. So, I'm trying in command prompt instead.
I'm using JDK 1.8.0.
1) First, I extracted all class files from their individual folders.
2) I created a manifest.txt which contains the following (including a carriage return at the end as described in the oracle tutorial)
Main-Class: Start
3) I'm creating the runnable jar with the following command, being verbose as possible to ensure correct versioning:
C:\correctDirectory\"C:\Program Files\Java\jdk1.8.0\bin\jar.exe" cvfm ERSR.jar manifest.txt *.class
4) That runs fine. I then inspect the JAR to ensure it containts the Start.class file which contains the main method:
C:\correctDirectory\"C:\Program Files\Java\jdk1.8.0\bin\jar.exe" tf ERSR.jar
The output of that is (reduced to useful info):
META-INF/
META-INF/MANIFEST.MF
Start.class
5) Then I run the JAR with the following command:
C:\correctDirectory\"C:\Program Files\Java\jdk1.8.0\bin\java" -jar ERSR.jar
To which I get the error:
Error: Could not find or load main class Start.
Thanks in advance kind folks.
Does your Start class contain any static field that is initialized with a contents of a resource (a .properties file, or alike)?
If that is the case, then it's likely the problem. The command you use in step 3) only packages the .class files into the JAR, but ignores the rest:
...\jar.exe cvfm ERSR.jar manifest.txt *.class
Modify it to include everything:
...\jar.exe cvfm ERSR.jar manifest.txt *
First post, so sorry for my poor formatting. I have a java program that I developed in eclipse. I exported the program as a jar (myJar.jar), and then I put all of the external jars that my program depends on into a folder called lib that lives in the same location as myJar.jar. In order to set my classpath I have a manifest file with the following format:
Main-Class: exe.myMain
Class-Path: lib/jar_1.jar lib/jar_2.jar ... lib/jar_n.jar
Manifest-Version: 1.0
However, when I attempt to run the program using "java -jar myJar.jar" the classes from the jars that live in lib are not being loaded (I'm getting a ClassNotFoundException) . I used the following code in my program to print the classpath:
ClassLoader cl = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader)cl).getURLs();
for(URL url:urls){
System.out.println(url.getFile());
}
And when I run this code the classpath is simply "myJar.jar".
I have two questions:
1.) Does the above code actually give me the classpath for the JRE at run time, or am I simply being given the address of my main class?
2.) Given the above code does indeed give me the classpath for the JRE at run time, am I doing anything wrong?
Please feel free to ask for more information, and I will happily provide what you need.
What you are doing sounds correct.
For some reason the Class-Path entry in the manifest does not show up when inspecting the classpath (e.g. here and here; those examples use the property "java.class.path" but my testing shows that ClassLoader.getURLs() behaves the same). It should still get searched for classes though. I don't know how to obtain the true classpath that includes the Class-Path entry from the manifest.
The first thing I'd like to check is that the file META-INF/MANIFEST.MF inside myJar.jar matches the manifest that you created. You can open myJar.jar by renaming it to have a .zip file extension.
I tried to replicate your problem but the classes in lib/jar_1.jar were loaded for me, so if META-INF/MANIFEST.MF is correct I'll describe what I did in detail so you can find what we are doing differently.
Edit:
Here are the steps I used:
Create a new directory called "experiment". The following steps are all to be done in that directory.
Create new directories called "jar_1", "lib", and "exe"
Create a file called "ClassInJar1.java" in directory "jar_1" with the following content:
package jar_1;
public class ClassInJar1 {
public static void method() {
System.out.println("Hello from ClassInJar1");
}
}
Run javac jar_1/ClassInJar1.java
Run jar cf lib/jar_1.jar jar_1/ClassInJar1.class
Create a file called "myMain.java" in directory "exe" with the following content:
package exe;
import java.net.*;
import jar_1.ClassInJar1;
public class myMain {
public static void main(String[] args) {
ClassLoader cl = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader) cl).getURLs();
for (URL url : urls) {
System.out.println(url.getFile());
}
ClassInJar1.method();
}
}
Run javac exe/myMain.java
Create a file called "manifest" in the "experiment" directory with the following content:
Main-Class: exe.myMain
Class-Path: lib/jar_1.jar lib/jar_2.jar
Manifest-Version: 1.0
Run jar cfm myJar.jar manifest exe/myMain.class
Run java -jar myJar.jar
Output:
/.../experiment/myJar.jar
Hello from ClassInJar1
Your manifest file is seem to be wrong. You have Main-Class: exe.myMain => java but have type of exe? Recommend for you is you should using eclipse to export your jar file it will auto create all things for you, you don't have to manually create manifest file so you can make mistake. See the detail as follow:
I have tested by created a java project with eclipse => using export function of eclipse to export a runnable JAR => using the 3rd option (copy required libraries into a sub-folder...). After exported I got the jar with name myJarName.jar and a folder with name myJarName_lib. Open the jar with 7zip program => under the META-INF => open the MANIFEST.MF => and here is the structure of it:
Manifest-Version: 1.0
Class-Path: . myJarName_lib/gson-2.8.0.jar myJarName_lib/jsoup-1.8.3.jar myJarName_lib/commons-cli-1.2.jar myJarName_lib/jackson-core-2.8.8.jar
Main-Class: upwork.Main
I have following class files,jar and manifest in a directory
Dot.class
Bridge.class
jsch.jar
MANIFEST.MD
Manifest file contains following two lines
Manifest-Version: 1.0
Main-Class:Dot
command used for creating jar file
jar cfm dot.jar MANIFEST.MD *
While executing generated jar it throws error saying no main manifest attribute
While seeing inside the generated jar META-INF folder contains auto generated manifest file, it doesn't have content for my main class.
I couldn't find successful steps ,Please correct me.
Had the same issue a few days ago and couldn't resolve it with the manifest file so I put the main class as a build parameter like this:
jar cfe Main.jar MainClass *.class
Add a space after ':' as in
Main-Class: Dot
Add a new line after the last line, in your case after Main-Class entry:
Manifest-Version: 1.0
Main-Class: Dot
The reason for 2. ist documented in https://docs.oracle.com/javase/tutorial/deployment/jar/modman.html in detail.
I tried below command and it works with the jar produced which i post.
java -cp "jsch.jar;." Dot
I've been learning about JAR files and wanted to try and create and run one myself. I carried out the following steps:
Created a project folder with a 'source' subfolder and a 'classes' subfolder
I wrote 2 source files, one with a main method which creates an instance of the other class and runs a simple method in it.
Compiled these to the 'classes' subfolder. I checked to see if they would run. They did
I created a manifest.txt file and filled in the Main-Class: xxxx and hit the return key. I saved this in the sources subfolder
Created a jar file in the classes subfolder by writing
jar -cvmf manifest.txt zzz.jar *.class
Tried to execute the jar file by typing
java -jar zzz.jar
This gives a ClassNotFound exception. If I try to execute the jar by double clicking on it in windows I get an errorbox saying "Could not find the main class xxxx"
I've double checked the spelling of the class inside the manifest file and it's correct.
Possibly important: I have to compile my programs using java -cp . xyz as there is an issue with my classpath. Does this mean that I need to execute jars in a different way as well? I tried
java -cp . -jar zzz.jar
but ended up with the same exception.
Edit: I ended up starting from scratch and now it runs (with the basic -jar zzz.jar command). Frustrating that I don't know what I was doing wrong but glad that it is working!
Shouldn't number 5. be run in the classes subfolder, where all your class files are? And if your classes are in packages, which they should be, you'll likely want to use * instead of *.class..?
To check what your jar file contains you can run:
jar tf zzz.jar
You will probably have to supply the entire path of the .class file you wish to execute after the classpath. ie java -cp xxx.jar classes.mainProgram.class. Where classes is the name of the folder which contains your class files.
in the java test I have :
package Tester.GUI.api
public class Test1{-----}
in the ".bat" :
<path to java> -classpath<all jar defined in the classpath separated by ";"> org.junit.runner.JUnitCore Tester.GUI.api.Test1
when I launch th ".bat" I have the following :
JUnit version 4.6
Could not find class: Tester.GUI.api.Test1
Time: 0,203
OK (0 tests)
I have verified jar files , typo but not found the cause
someone could help please?
The -classpath option needs to take a set of directies and/or jar files. Currently those are missing, so your main class (JUnitCore) is being used as the classpath, and Test1 used as the main class. I'm guessing you want JUnitCore as the main class and Test1 as the argument.
Try something like this (substituting the actual names of the jars you're using for jar-file1, jar-file2):
java -classpath <jar-file1.jar>;<jar-file2.jar> org.junit.runner.JUnitCore Tester.GUI.api.Test1
Edit:
Assuming jar files are specified correctly, the error message indicates that the Test1 class isn't on the classpath. If you're using an IDE, you need to find the output directory for compilation (for example, in Eclipse it is <project>/bin by default). Within this directory you will find other directories with the structure Tester/GUI/api. A file called Test1.class will be in the api directory. It is this output directory that needs to be added to the classpath (that is, the one above the Tester/GUI/api structure).
It says that the class that it cannot find is Tester.GUI.api.Test1. What directory are you running the test from, and what directory is your Test1 code in?
If you set the -classpath variable, you may also need to include the current directory in your classpath. So, if your original command was
java -classpath C:\foo.jar;D:\bar1\bar2.jar org.junit.runner.JUnitCore Tester.GUI.api.Test1
you could add the current directory to your classpath by adding ;. to the end of your -classpath option like this:
java -classpath C:\foo.jar;D:\bar1\bar2.jar;. org.junit.runner.JUnitCore Tester.GUI.api.Test1
This will work as long as the Test1 class is in the Tester\GUI\api directory under the current directory.
The tricky thing with setting the classpath in Java is that you don't want to give the directory where your actual .java files are, but instead you want to give the directory under which you can find the directories that are named for the packages in your code.
For example, if I compiled a class Foo in a package bar.baz, then I should have a file named Foo.class in a directory named baz inside another directory named bar. If I want to include Foo in my classpath, and if Foo.class is located at
C:\Users\Joe\Code\bar\baz\Foo.class, then I have to either run
java -classpath C:\Users\Joe\Code [main class goes here]
or else I have to change my directory to C:\Users\Joe\Code and run
java -classpath . [main class goes here]