Reputation: 2050
I need to create a jar file and not use maven or gradle packages.
First of all - I used all options that I saw in StackOverflow, so please, do not mark this question as duplicated
if you are not sure about the solution that you will find - more of them I have tried.
Project structure:
\src
---\Main.java
---\A.java
---\B.java
Steps:
1. Compiling:
javac \src\*.java
\src
---\Main.class
---\A.class
---\B.class
2. MANIFEST file created:
Manifest-Version: 1.0
Main-Class: src.Main
3. Compiling to the jar:
jar cfm test.jar MANIFEST.MF src/
4. Launching:
java -jar test.jar
result:
no main manifest attribute, in test.jar
Also I was trying following:
jar cvfe myjar.jar src.Main src\*.class
and many other options - the same result
How to correctly create a jar file natively?
Upvotes: 0
Views: 818
Reputation: 135
The Name-Value lines of the Manifest file must be terminated by a newline (CR LF
, CR
or LF
) according the JAR Specification:
section: *header +newline nonempty-section: +header +newline newline: CR LF | LF | CR (not followed by LF) header: name : value
Since the manifest file contains Main-Class: src.Main
but it is not being recognized ("no main manifest attribute..."), the newline is probably missing after that line - the last line.
Some editors do not add a newline at the end of the file.
To avoid that problem always include an empty line at the very end of the Manifest file.
very old problem, I would expect the jar
tool to correct that, or at least warns about it
Upvotes: 0
Reputation: 191743
$ java -version
java version "17.0.3" 2022-04-19 LTS
Java(TM) SE Runtime Environment (build 17.0.3+8-LTS-111)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.3+8-LTS-111, mixed mode, sharing)
$ javac -version
javac 17.0.3
Use a Makefile
JAVAC=javac
MAIN_CLASS=Main
APP_NAME=app
sources = $(wildcard src/*.java)
classes = $(sources:.java=.class)
all: program
program: $(classes)
clean:
@rm -rf out/
@rm *.jar
%.class: %.java
@$(JAVAC) -d out $<
jar: $(classes)
@jar -v --create --file $(APP_NAME).jar --main-class $(MAIN_CLASS) -C out/ .
exec: jar
java -cp .:out -jar $(APP_NAME).jar
.PHONY: all program clean jar
Folder structure
├── Makefile
└── src
└── Main.java
$ make clean exec
added manifest
adding: Main.class(in = 413) (out= 288)(deflated 30%)
java -cp .:out -jar app.jar
Hello world
Upvotes: 0
Reputation: 2999
DemoApp
├── MANIFEST.MF
└── src
├── A.java
├── B.java
└── Main.java
Manifest-Version: 1.0
Main-Class: Main
No package
import java.util.Calendar;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
System.out.println(new A().hello("WORLD"));
System.out.println(new B().echo(Calendar.getInstance().getTime().toString()));
}
}
javac src/*.java -d out
DemoApp
└── out
├── A.class
├── B.class
└── Main.class
cp MANIFEST.MF out/
DemoApp
└── out
├── A.class
├── B.class
├── Main.class
└── MANIFEST.MF
cd out
jar cfm ../app.jar MANIFEST.MF *.class
cd ..
DemoApp
├── app.jar
├── MANIFEST.MF
├── out
│ ├── A.class
│ ├── B.class
│ ├── Main.class
│ └── MANIFEST.MF
└── src
├── A.java
├── B.java
└── Main.java
java -jar app.jar
app.jar
├── A.class
├── B.class
├── Main.class
└── META-INF
└── MANIFEST.MF
DemoApp
└── src
├── A.java
├── B.java
└── Main.java
javac src/*.java -d out
DemoApp
├── out
│ ├── A.class
│ ├── B.class
│ └── Main.class
└── src
├── A.java
├── B.java
└── Main.java
jar cfe app.jar Main -C out /
DemoApp
├── app.jar
├── out
│ ├── A.class
│ ├── B.class
│ └── Main.class
└── src
├── A.java
├── B.java
└── Main.java
java -jar app.jar
Upvotes: 1