I have some Java code on my machine that I run from the command line. I want to create a runnable .jar file from this code so that I can distribute my application more easily.
The code is in four folders, called fol_a, fol_b, fol_c, and fol_d. Each of these contains a /bin subfolder, containing the .class files, and two of them (fol_a and fol_b) also contain a /lib folder, containing some .jar files that the code needs.
fol_d contains the class to run, Demo, which is in a package called machineLearning. The full path to the class is
fol_d/bin/machineLearning/Demo
I currently run the code from the command line as follows:
$ cd fol_d/bin
$ java -cp ".:../../fol_a/bin:../../fol_a/lib/*:../../fol_b/bin:../../fol_b/lib/*:../../fol_c/bin" machineLearning.Demo <param_1> <param_2> ... <param_5>
where <param_1> to <param_5> are the arguments given to the Main method in Demo.
What I want is to create one single .jar file that contains all the code that is necessary to execute Demo successfully, i.e., the code in fol_a through fol_d. I then want to be able to run this .jar file from the command line, giving it the arguments that go to the Main method in Demo. Something like this:
$ java -jar MyApplication.jar <param_1> ... <param_5>
Is this possible? How would I do this? I've been trying to find an answer online, but the amount of information confuses me.
UPDATE
Right! So it seems that all I needed to do was this:
copy the contents of the bin directories to a new dir myapp
make a manifest.txt file that specifies the main class to run, as well as the classpath
jar myapp: $ jar cmf manifest.txt myapp.jar -C myapp/ .
execute the jar: $ java -jar myapp.jar <arg_1> <arg_2> ... <arg_n>
Yes it is possible.
Use "cp -R" to copy all 4 folders' bin directories into one directory ... preserving the subdirectory structures. (Read man cp if you don't understand how. Install the manual entries if they are not installed.)
Use the jar command to create the JAR file from the consolidated directory.
UPDATE
When you create the JAR file, the paths within the JAR (i.e. in the JAR file index) must match the respective classes fully qualified names.
If you are creating an executable JAR, the Main Class attribute must specify the fully qualified class name.
If you misname the JAR file entries then either java won't find the classes, or it will refuse to load them because the pathname and classname don't match.
These requirements apply for all JARs, but from your comments it seems that you have overlooked this.
In your comment, you seem to have used the wrong classname in the Main Class attribute ... unless you declared the class in the fol_d.bin package!
UPDATE 2
Here is an example to illustrate my point about fully qualified classnames
package foo.bar;
public class Main {
...
}
The simple class name is Main. The fully qualified classname is foo.bar.Main. If you put the ".class" file for this class into a JAR, the pathname in the JAR file for the class must be:
/foo/bar/Main.class
The package name (foo.bar) maps to the directory path in the JAR file index; i.e. "/foo/bar".
If the pathname in the JAR file isn't that, then the classloader won't find it.
Related
I have just shifted back from an IDE to Notepad to write a Java program. The program is using 20 JARs. I compiled successfully. When I decided to run the Java class file using
java -cp ".\\*" MyProgram
it was giving the standard error "Couldn't find or load main class....".
I was confused because when I used to run the java command with all files in an existing folder, it would just get those JARs as the current folder is already in the classpath. As the program is running from the current folder, I tried using -cp "." to include it explicitly in the classpath but that didn't work either.
Finally I was able to run the program with this command:
java -cp ".\\*;." MyProgram.java
I am asking this question to understand the actual logic behind Java's classpath.
Correct me if I am wrong, but I think that the JAR is just a standard archive in which all the packages are encapsulated in respective folders. If all the JARs are in my current folder including my main class file then why can't I run it with:
java -cp "." MyProgram
or simply:
java MyProgram
If the problem is with the multiple JAR files to include and that's why we used ".\\*" to include all the JARs in the classpath, then why do we have to explicitly include the current folder again in the classpath using:
java ".\\*;." MyProgram
To include all jar required to run your program in command prompt use wildcard *:
java -classpath E:\lib\* HelloWorld
You are using "." that defines current directory and "./*" defines all files in current directory.
The class path is a list of jar files and directories containing the classes and resources of your program. Mentioning a jar file adds its contents to the class path.
"./*" will get you only the jar files in the current directory, "." adds the current directory to the class path. This allows to access all classes (and the jar files as raw file resources but not its contents, i.e. the classes contained in them).
If you need both in the class path, you have to specify both.
You've answered your own question, sort of.
. means that it will look for .class files in the current directory.
JARs act just like a directory. So to have the abc.jar "directory" you would specify abc.jar in your classpath.
If you need both the .class files present in the current directory, and the .class files packaged into JARs found in the current directory, you would have the following classpath: -cp ".:*.jar
All the answers here are telling you to use the wildcard without extension (* or ./*) but this is a bad practice, you don't want Java to go look into irrelevant files, so specify the extension: *.jar.
"." means current directory not files in the directory
"./*" means all files in current directory.
So you want to use all jars in current directory so 2nd will work
I have a Java project with 5 packages and 30 classes. I want to test this project on a different computer, but I can't install any sotware on that computer so I can't use things like Maven, Eclipse etc. Is there a way I can execute the program on that computer?
What I tried to do, is to compile the project using Eclipse on my computer, then went to the other computer and tried to execute the project main class via the folder that the main class .class file is at.
I.E., say that the main class name is Hello in package Greetings and Hello.class is at folder named folder. So I opened the command line window at folder and typed the command:
java Greetings.Hello
That didn't work....
Edit: After doing this I got the message: Error: Could not find or load main class Greetings.Hello
If the package name is Greetings and you want to run Hello.class
Hello class must have main method.
Hello.class must in folder name Greetings (package name).
Execute java Greetings.Hello from the one level above of Greetings folder
It seems to me Hello.class is not inside of Greetings folder
If javac is installed on the system you can directly compile on the system. you can compile even large projects including many packages with choosing different options provided by javac.
The javac tool reads class and interface definitions, written in the Java programming language, and compiles them into bytecode class files. It can also process annotations in Java source files and classes.
There are two ways to pass source code file names to javac:
For a small number of source files, simply list the file names on the command line.
For a large number of source files, list the file names in a file, separated by blanks or line breaks. Then use the list file name on the javac command line, preceded by an # character.
Source code file names must have .java suffixes, class file names must have .class suffixes, and both source and class files must have root names that identify the class. For example, a class called MyClass would be written in a source file called MyClass.java and compiled into a bytecode class file called MyClass.class.
Inner class definitions produce additional class files. These class files have names combining the inner and outer class names, such as MyClass$MyInnerClass.class.
You should arrange source files in a directory tree that reflects their package tree. For example, if you keep all your source files in C:\workspace, the source code for com.mysoft.mypack.MyClass should be in C:\workspace\com\mysoft\mypack\MyClass.java.
By default, the compiler puts each class file in the same directory as its source file. You can specify a separate destination directory with -d source
Given that you have Eclipse and you ran the code in Eclipse: the quickest way is to use Eclipse and export it to executable JAR.
If you have Run Configuration (e.g. named Hello) that you use for running the code:
Menu -> Export -> Runnable JAR file
Launch Configuration: Hello
Select export destination: (e.g. C:\tmp\Hello.jar)
Set Extract required libraries into generated JAR
Click finish.
This will create Hello.jar file you can execute typing in:
java -jar Hello.jar
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.
Hi all,
I have about 10 jars and when I run my program I invoke the following:
java -Xmx1024m -cp a.jar;b.jar;c.jar;whatever.jar -Dfile.encoding=UTF-8 [package][class]
I want to make this as an executable jar. I thought that when I unjar (that sounds weird, but I'm using java command - not using general zip program) the jar containing [package][class], update manifest.mf and rejar it. Unfortunately, this did not work.
Is it possible for me to make it as an executable jar or I should unjar it and sum it all?
You just need this line in your manifest file
Main-Class: my.package.Main
Then run the jar command with the m flag, and give it the name of your manifest file:
jar cmf manifest main.jar *.class
Unfortunately, jars can't contain other jars. Give the jar containing your entry point a Main-Class, and then set the classpath so that the other 9 jars are accessible.
Jar is a collection of files. To make a jar an executable the most important thing is that it should contain a class that has the main() method. So, you can make a jar executable only if contains a .class file that has a main method. That class will look like this.
public class AClass
{
public static void main(String[] args)
{
...
}jar
...
}
Then and only then can you make a jar executable.
If the main() method class is present. Then to make the jar executable do this.
Extract the jar
In the manifest file add this line Main-Class:AClass and don't forget to press enter after this line. follow this link
Rejar the class files. You got the executable jar now
To execute the jar, (suppose you made a.jar executable), then run java -jar a.jar to run the jar file.
Second thing is that the command that you have posted in the question does not require those jars to be executable. When you use -cp, then the parameters (i.e. a.jar etc..)are basically libraries or in other words, when java will look for a class file to find definition of a class or a function or whatever for that matter, it will look inside these jars if what it is looking for is not part of the java standard library.
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]