简体   繁体   中英

How to compile and run a runnable JAR using only javac and jar

How can I compile and run a runnable JAR file using only javac and jar ? I don't want to build the JAR file with an IDE or with tools like Gradle, Maven, or Ant, because I want to understand, for my own edification, how I can compile a runnable JAR using only javac and jar , and then how to correctly run this JAR with java .

I have tried building the JAR like this:

$ javac Example.java
$ file Example.class
Example.class: compiled Java class data, version 55.0
$ jar cvf Example.jar Example.class
added manifest
adding: Example.class(in = 682) (out= 456)(deflated 33%)
$ file Example.jar
Example.jar: Java archive data (JAR)

Then I tried various ways to execute the JAR, but none of them worked:

$ java -jar Example.jar main
no main manifest attribute, in Example.jar
$ java -cp '.;Example.jar' main
Error: Could not find or load main class main
Caused by: java.lang.ClassNotFoundException: main
$ java -cp '.;Example.jar' Example
Error: Could not find or load main class Example
Caused by: java.lang.ClassNotFoundException: Example
$ java -cp '.;Example.jar' -jar Example.jar Example
no main manifest attribute, in Example.jar
$ java -cp '.;Example.jar' -jar Example.jar main
no main manifest attribute, in Example.jar

My code, just to show I have an Example class and a main() function:

import java.util.ArrayList;
import java.util.List;

public class Example {
    private static class A {
        public int x = 7;
    }

    public static void main(String[] args) {
        List<A> list = new ArrayList<>();
        A a = new A();
        list.add(a);
        a.x = 5;
        System.out.println(a.x);
        System.out.println(list.get(0).x);
    }
}

My javac , jar , and java tools are all version 11.0.15.

I tried looking at the answers on Compile and run with javac and java using classpath classes in jar and javac compiles files and jars but java fails , but none of the suggestions in the answers to these two questions worked for me.

Thanks to @f1sh and @pdem, I found an answer:

$ javac Example.java
$ jar cfe Example.jar Example Example.class 'Example$A.class'
$ java -jar Example.jar
5
5

Is @f1sh points out in there comment, I needed to (A) include the Example$A.class class when creating the JAR, and (B) run the java command with the correct arguments.

As for making the JAR executable, a manifest file is required. A manifest file can be created manually, or you can let jar create it for you with the e option. The general format for using the e option is

java cfe <name of jar> <name of main class> <list of .class files>

For more info on using the e option or writing a manifest file by hand, see Setting an Application's Entry Point or one of the other child pages of Working with Manifest Files: The Basics .

goose@t410:/tmp$ javac Example.java 
goose@t410:/tmp$ jar cvfe example.jar Example Example*.class 
added manifest
adding: Example$A.class(in = 293) (out= 233)(deflated 20%)
adding: Example.class(in = 682) (out= 457)(deflated 32%)
goose@t410:/tmp$ java -jar example.jar 
5
5

Note the penultimate argument to jar is the name of the main class

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM