Bundling JAR dependencies with executable JAR (Über JAR) from command line - java

I'm trying to create an executable jar from the command line. The main class in the JAR has dependencies that i have packaged into another plain JAR file.
I want to package the dependency JAR together with the executable JAR in order to have a single JAR file to ship.
What i have tried so far is the following:
The dependency Hello.class file has the mock code:
public class Hello {
public String getHello() {
return "Well hello there!!";
}
}
I have packaged class file into hello.jar using:
jar cvfM hello.jar Hello.class
The hello.jar content is now:
hello.jar -+- Hello.class
Now i have the main class with the mock code:
public class Main {
public static void main(String[] args) {
System.out.println(new Hello().getHello());
}
}
I then create a manifest file manifest.txt with the following content:
Main-Class: Main
Class-Path: hello.jar
I now create the executable JAR using:
jar cvfm main.jar manifest.txt Main.class hello.jar
The main.jar content is now:
main.jar -+- Main.class
|
+- hello.jar
|
+- META-INF -+- MANIFEST.MF
Running the executable JAR using:
java -jar main.jar
I get a class loader error for the Hello class dependency. I understand that this is because the class loader looks for hello.jar in the same path as main.jar. So when i put a copy of hello.jar alongside main.jar i am able to run it.
What do i need to do in order to be able to run main.jar with hello.jar inside of it?
I know that you will ask: "why is he trying to do it this way?". I know that ppl mostly use Eclipse, Ant, Maven or other tools to do this. But please just humor me :)

Your approach is completely wrong unfortunately.
There is no "normal" way to place a jar inside of another jar. So your hello.jar has nothing to do inside of main.jar! The point is the "normal" classloader wont look for jar files inside of jars, hence you get the class not found error.
However: if you want desparetly to do that, then google for "OneJar" and go to http://one-jar.sourceforge.net/

There's no easy way to do this. That is, you are going to have to write your own classloader if you want to nest jars inside a jar.
There are several products out there that already support this for you. One-Jar is one of them that I've used with a lot of success -- can easily ant script it.
Here is an interesting SO discussion on the whole topic --
Easiest way to merge a release into one JAR file

Well, I believe you may be facing a jar generation bug. Check out this link, it might enlight you.
A teaser:
As far as I aware, and based on my own attempts, there's no
way to specify a Class-Path that makes the class loader
look in embedded jar files. See the preceeding paragraph
for a description.
Therefore, you may check one of the following links:
classpath-including-jar-within-a-jar, java-easiest-way-to-merge-a-release-into-one-jar-file
Cheers!

Related

Can't figure out how to run my jar file "could not find or load main class"

I'm trying to create a jar file and run it using java -cp main.jar com.test.Foo.Main but I keep getting:
Error: Could not find or load main class com.test.Foo.Main
Caused by: java.lang.ClassNotFoundException: com.test.Foo.Main
This is my file structure. So I'm thinking the line in my Main.java should be package com.test.Foo correct?
I'm compiling my Main.java with javac Main.java which outputs a Main.class file. Afterward, I create a jar file using jar cfm main.jar META-INF/MANIFEST.MF Main.class and finally while I'm in the same directory as the jar file <root>/src/com/test/Foo/ I run java -cp main.jar com.test.Foo.Main and that's when I run into the above error. Any idea how I can run this file like this (and yes I need it to run with this command specifically)?
Main.java
package com.test.Foo;
public class Main {
public static void main (String args[]) {
System.out.println("I am com.test.Foo.Main");
}
}
META-INF/MANIFEST.MF
Manifest-Version: 1.0
Main-Class: com.test.Foo.Main
I tried using some of the options given in this popular SO question and nothing helped.
The picture you're showing in your question is your project structure not your jar structure.
When you create a jar file, the structure for that jar file might be
different with your source code folder structure.
Every IDE (such as eclipse, netbeans, IntelliJ) has a mechanism for creating JAR files. In your case when you open the created jar file (using zip apps like winrar) you should see something like this :
com
|
test
|
Foo
|
Main
META-INF
|
MANIFEST.MF
This should be the ordering of your files and folders, otherwise Java can not find your main class from MANIFEST.MF
Now to solve this problem:
Open your jar file using a zip application like winrar
check the folder structure residing inside your jar file as I draw
Fix it right away within the winrar or try to correct your project structure to produce the structure I mentioned.
The class is called com.test.Foo.Main you need to specify the full name in the command:
java -cp main.jar com.test.Foo.Main
or you can use the simpler
java -jar main.jar
Check your META-INF/MANIFEST.MF for the attribute of Manifest-Version: 1.0
This attribute must be there.
Edit:
You need to move to the source root src/ and issue below command to create a valid jar.
javac com/test/Foo/*.java
and, create the jar using,
jar cmf com/test/Foo/MANIFEST.MF main.jar com/test/Foo/*.class
The thing is, package structure should match with the folder structure apparently.

Command line java error: Could not find or load main class

I'm trying to run a project from the command line (Ubuntu 14.04). The main class is called Demo, and I have a Demo.java, a Demo.class, and a Demo$1.class all in the same directory (I know it would be better to seperate them).
I wrote my own Manifest file, MANIFEST.MF, which just looks like this:
Main-Class:Demo
I made sure to end it with a newline.
Next, I want to create my .jar file. I did so with this command:
jar -cfm example.jar MANIFEST.MF *.class
Then, I try to run my project like so:
java -Djava.library.path=/path/to/dependencies -jar example.jar
I seem to get the following error no matter what I try:
Error: Could not find or load main class Demo
I've actually never compiled/run a Java project from the command line before, it's possible I'm making a stupid mistake and just can't figure it out. Any help is appreciated!
EDIT: Here are the contents of example.jar, according to vim:
" zip.vim version v27
" Browsing zipfile /home/ellen/bendersexample2/src/bendersexample/example.jar
" Select a file with cursor and press ENTER
META-INF/
META-INF/MANIFEST.MF
AnnotatedBenders.class
Demo$1.class
Demo.class
Demo$ModelType.class
ManualBenders$1.class
ManualBenders$BendersCallback.class
ManualBenders.class
Model.class
Problem.class
Solution.class
Solution$Verbosity.class
StandardModel.class
Here are the contents of the META-INF/MANIFEST.MF which is in the jar:
Manifest-Version: 1.0
Created-By: 1.8.0_161 (Oracle Corporation)
Main-Class: Demo
UPDATE: Here are the interesting parts of Demo.java:
package bendersexample;
public final class Demo {
/* Some functions */
public static void main(final String[] args) {
/* Some code */
}
}
I changed my MANIFEST.MF to the following:
Main-Class:bendersexample.Demo
And re-generated the example.jar file. I still get the following:
Error: Could not find or load main class bendersexample.Demo
Could there be an issue with how I generate my class files?
To generate the class files initially, I did the following:
javac -classpath .:/opt/ibm/ILOG/CPLEX_Studio_Community128/cplex/lib/cplex.jar *.java
Please let me know what else I should try! Thank you
The problem was just that had the Manifest in the /bendersexample folder and the was creating the .jar in this folder as well! I just needed to move that stuff into the parent directory and everything worked fine!
The final Manifest file used bendersexample.Demo as the Main-Class, and the jar was created and run from /bendersexample 's parent directory.
If anyone runs into this problem I would recommend taking a look at your project's structure before trying anything else, because this turned out to be a very easy fix!

Jar file couldn't load or find main class

I've been trying to run a app from a Jarfile, but it keeps printing out:
"cannot find or load main class ...".
I tried to solve this problem using infos from this thread but all seemed to be useless. To be honest, I'm getting desperate because of the fact that this is such a trivial problem.
Anyways, what I did:
Main-Class: com.test.Test
my manifest attribute:
jar cfm test.jar manifest.txt <full_path>/out/com/test/*.class
which is what's packaged into the jar file (the Test.class file)
The Test class:
package com.test;
public class Test {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
You should package the class correctly. Do
jar cfm test.jar manifest.txt com/test/*.class
in the parent folder of the folder com. By providing the absolute path (the way you did), the class file is packaged incorrectly.
Firstly, just in case you are using Eclipse IDE, there is some tools like the Fat Jar Plugin which are able to help you to package your build.
Secondly, there is Maven, to handle your dependencies, and build the package you need with everything ok. In your case, I will look for the Apache Maven Jar Plugin.
Finally, the old school way to go with the commandline, as you tried to do.
As Eliott Frisch has said in your question comments, you don't need to provide the fullpath to the mainclass inside your jar cfm test.jar manifest.txt <full_path>/out/.
And what's because the manifest.txt already give the package information!

Export project as jar file using manifest [duplicate]

This question already has an answer here:
Exporting executable/runnable jar in eclipse
(1 answer)
Closed 7 years ago.
I just wrote Java console project , which i shoud pack as jar file. I googled it alot and found different solutions like (Eclipse) Project -> New Configuration -> e.t.c Then export as jar file using speciefied config. That's nice, but it's not what i need. After making repeatedly - it won't work. I tried to do same as mentioned here: click
Second Solution: create jar using manifest. Well it's much better, because i can specifiy entry point of main.class. But it's won't work due to can;t find out where's annother packages.
Upd: Launcher.class looks like this
package backpack.dao;
public class Launcher{
public static void main(String[] args){
Backpack.start();
}
}
My project structure:
src/backpack/dao/Item.java
/Backpack.java
/Chromo.java
src/backpack/main/launcher/Launcher.java
The Question is: What should i write in manifest instead of this:
Main-Class src/backpack/main/launcher/Launcher to make executable jar
successfully?
P.S Launcher class uses instances from Backpack.java
Please don't downgrade. I'm rookie
Thanks
What is the package of the Launcher.java? Have you included package name to the classname in manifest.txt?
Remember, when Launcher.java is in package "backpack.main.launcher" your classname in manifest.txt will be:
Main-Class src/backpack.main.launcher.Launcher
instead of:
Main-Class src/backpack/main/launcher/Launcher
Also, remember about this:
The text file must end with a new line or carriage return.
To check what exactly is wrong with your jar file run it in the command line using:
java -jar MyJar.jar
and paste here output with error message.
For more help you can check this example from Oracle: link
Edit:
I recreated your project structure and I have found the solution (at least I think I have :) )
Compile your code and go to the parent directory with compiled code (with *.class files, this should be "out" directory or something like this - depending from your IDE). For example: when your project is in some/path/src/backpack/main/launcher go to src directory.
Run command:
jar cvfe MyJar.jar backpack.main.launcher.Launcher -C . .
(Yes, two dots at the end)
This should create jar with name MyJar.jar and manifest file (-e flag) with main class backpack.main.launcher.Launcher. -C flag include all *.class files recursively from directory . (current one), so both from dao and launcher package.
Test jar: java -jar MyJar.jar

java compiling with jars

I'm trying to figure out how an existing Java program (I did not make myself ofcourse) was compiled with existing jars
I have Test.java (original source file):
package Demo;
//import classes from jars here etc...
public class Test {
public static void main(String args[]) {
etc...
}
}
Now I have two other jars:
file1.jar
file2.jar
Demo.jar
There is a batch script to run it:
#echo off
set CLASSPATH="file1.jar";"file2.jar";"Demo.jar"
java -cp %CLASSPATH% Demo.Test
This WORKS, but now I need to change the source file Test.java, recompile and run with the jars class dependencies. (sorry if I'm not making sense)
Now, I have tried to recompile this to reproduce same results with no luck:
javac -cp file1.jar;file2.jar;Demo.jar Test.java
defined manifest:
manifest.mf
Main-class: Demo.Test
Created directory "store" for class files and moved class files there
Ran:
jar -cmf manifest.mf Demo.jar store
Which created the "Demo.jar"
Then I ran the run the batch script above but not the same results (doesn't work at all)
Any help would be appreciated. Thank you!
It is difficult to create true executable jars as soon as you rely on external jars.
The only solution here is to :
put all jars in the same folder : yours and its dependencies
add a classpath entry inside your manifest
launch the jar using java -jar Demo.jar
The manifest will have to look like :
manifest.mf
Main-class: Demo.Test
Class-Path: file1.jar file2.jar

Categories

Resources