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

Time:08-26

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.

CodePudding user response:

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.

CodePudding user response:

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

  • Related