JAR(1)

πŸ“¦ version 22.0.2.0, in opensuse-leap 16.0

πŸ’… JAR(1) β€” the JDK Commands glow-up, bestie edition

Okay so like, imagine you're on the command line and you need to deal with an archive. That's jar. She's the JDK Commands girlie for this job, and she is literally about to make your whole build system make sense. Strap in. πŸŽ€

The manual name is JAR(1) β€” yep, that's her. And this whole page? It lives in the JDK Commands section. Slay.


✨ NAME ✨

jar β€” create an archive for classes and resources, and manipulate or restore individual classes or resources from an archive. No cap, that's the whole vibe. She builds the archive, she digs through it, she pulls stuff back out. Multi-talented icon. πŸ‘‘


🌸 SYNOPSIS 🌸

jar [OPTION ...]  [ [--release VERSION] [-C dir] files] ...

That's the shape of it. Options first, then optionally a --release VERSION, then optionally -C dir, then your files. Periodt.


πŸ¦‹ DESCRIPTION πŸ¦‹

So the jar command is a general-purpose archiving and compression tool, and she's built on top of the ZIP and ZLIB compression formats. Like, that's her whole foundation.

Fun little history moment: jar was initially designed to package Java applets (which btw are not supported since JDK 11, rip) or applications. But beginning with JDK 9, users can use the jar command to create modular JARs. And honestly? For transportation and deployment, it's usually more convenient to package modules as modular JARs. That's the move.

The syntax for the jar command resembles the syntax for the tar command β€” they're giving cousin energy. She has several main operation modes, each defined by one of the mandatory operation arguments. Other arguments are either options that modify the behavior of the operation, or they're required to perform the operation. Simple as that.

When modules or the components of an application (files, images and sounds) are combined into a single archive, they can be downloaded by a Java agent (such as a browser) in a single HTTP transaction, rather than requiring a new connection for each piece. And this dramatically improves download times. Iconic behavior. The jar command also compresses files, which further improves download time. Plus she enables individual entries in a file to be signed so that their origin can be authenticated. And a JAR file can be used as a class path entry, whether or not it's compressed. Versatile queen. πŸ’–

An archive becomes a modular JAR when you include a module descriptor, module-info.class, in the root of the given directories or in the root of the .jar archive. The following operations described in Operation Modifiers Valid Only in Create and Update Modes are valid only when creating or updating a modular jar or updating an existing non-modular jar:

  • --module-version
  • --hash-modules
  • --module-path
Note: All mandatory or optional arguments for long options are also mandatory or optional for any corresponding short options. Like, don't think you can skip the long version's rules just because you used the short one. She's not having it. πŸ™ˆ

πŸ‘‘ MAIN OPERATION MODES πŸ‘‘

When using the jar command, you must specify the operation for it to perform. Non-negotiable. You specify the operation mode for the jar command by including the appropriate operation arguments described in this section. And you can mix an operation argument with other one-letter options. Generally the operation argument is the first argument specified on the command line. Main character energy β€” she goes first.

  • -c or --create β€” Creates the archive. Fresh out of the box, brand new. ✨
  • -i FILE or --generate-index=FILE β€” Generates index information for the specified JAR file. Heads up bestie: this option is deprecated and may be removed in a future release. So enjoy her while she's here. πŸ’€
  • -t or --list β€” Lists the table of contents for the archive. Peek inside, see what's there. πŸ‘€
  • -u or --update β€” Updates an existing JAR file. Glow-up, not rebuild.
  • -x or --extract β€” Extracts the named (or all) files from the archive. Unpacking, but make it cute. 🧚
  • -d or --describe-module β€” Prints the module descriptor or automatic module name. The receipts, basically.

🌈 OPERATION MODIFIERS VALID IN ANY MODE 🌈

You can use the following options to customize the actions of any operation mode included in the jar command. Universal modifiers, we love to see it.

  • -C DIR β€” Changes the specified directory and includes the files specified at the end of the command line. Then she hits you with this little syntax reminder:
jar [OPTION ...]  [ [--release VERSION] [-C dir] files]
  • -f FILE or --file=FILE β€” Specifies the archive file name. Like, which archive are we talking about? This one. πŸŽ€
  • --release VERSION β€” Creates a multirelease JAR file. Places all files specified after the option into a versioned directory of the JAR file named META-INF/versions/VERSION/, where VERSION must be must be a positive integer whose value is 9 or greater. (Yes that double "must be" is in the original, she said it twice, she meant it twice. πŸ’…)

At run time, where more than one version of a class exists in the JAR, the JDK will use the first one it finds, searching initially in the directory tree whose VERSION number matches the JDK's major version number. It will then look in directories with successively lower VERSION numbers, and finally look in the root of the JAR. Like a little search party, descending. πŸ”

  • -v or --verbose β€” Sends or prints verbose output to standard output. She's telling you everything.

πŸ“ OPERATION MODIFIERS VALID ONLY IN CREATE AND UPDATE MODES πŸ“

You can use the following options to customize the actions of the create and the update main operation modes. Create-and-update girlies only, sorry to the rest.

  • -e CLASSNAME or --main-class=CLASSNAME β€” Specifies the application entry point for standalone applications bundled into a modular or executable modular JAR file. The main character of your app, literally. πŸ‘‘
  • -m FILE or --manifest=FILE β€” Includes the manifest information from the given manifest file. Receipts incoming.
  • -M or --no-manifest β€” Doesn't create a manifest file for the entries. She's going manifest-free, living her truth.
  • --module-version=VERSION β€” Specifies the module version, when creating or updating a modular JAR file, or updating a non-modular JAR file. Gotta label your work.
  • --hash-modules=PATTERN β€” Computes and records the hashes of modules matched by the given pattern and that depend upon directly or indirectly on a modular JAR file being created or a non-modular JAR file being updated. Very rigorous, very meticulous. πŸ”₯
  • -p or --module-path β€” Specifies the location of module dependence for generating the hash. Where the deps live.
  • @file β€” Reads jar options and file names from a text file as if they were supplied on the command line. The at-sign is doing the heavy lifting, we stan. 🫢

πŸ’œ OPERATION MODIFIERS VALID ONLY IN CREATE, UPDATE, AND GENERATE-INDEX MODES πŸ’œ

You can use the following options to customize the actions of the create (-c or --create) the update (-u or --update) and the generate-index (-i or --generate-index=FILE) main operation modes. The trio zone.

  • -0 or --no-compress β€” Stores without using ZIP compression. Sometimes you just want raw storage, and that's valid. ✨
  • --date=TIMESTAMP β€” The timestamp in ISO-8601 extended offset date-time with optional time-zone format, to use for the timestamp of the entries, e.g. "2022-02-12T12:30:00-05:00". Time-zone girlies rise up. πŸ•°οΈ

🌟 OTHER OPTIONS 🌟

The following options are recognized by the jar command and not used with operation modes. Side quests only.

  • -h or --help[:compat] β€” Displays the command-line help for the jar command or optionally the compatibility help. She's helping, always.
  • --help-extra β€” Displays help on extra options. Bonus help, for the extra girlies.
  • --version β€” Prints the program version. Identity check. πŸͺͺ

🧚 EXAMPLES OF JAR COMMAND SYNTAX 🧚

These are the little demo moments, and honestly? They ate.

  • Create an archive, classes.jar, that contains two class files, Foo.class and Bar.class.
jar --create --file classes.jar Foo.class Bar.class
  • Create an archive, classes.jar, that contains two class files, Foo.class and Bar.class setting the last modified date and time to 2021 Jan 6 12:36:00.
jar --create --date="2021-01-06T14:36:00+02:00" --file=classes.jar Foo.class Bar.class
  • Create an archive, classes.jar, by using an existing manifest, mymanifest, that contains all of the files in the directory foo/.
jar --create --file classes.jar --manifest mymanifest -C foo/
  • Create a modular JAR archive, foo.jar, where the module descriptor is located in classes/module-info.class.
jar --create --file foo.jar --main-class com.foo.Main --module-version 1.0 -C foo/classes resources
  • Update an existing non-modular JAR, foo.jar, to a modular JAR file.
jar --update --file foo.jar --main-class com.foo.Main --module-version 1.0 -C foo/module-info.class
  • Create a versioned or multi-release JAR, foo.jar, that places the files in the classes directory at the root of the JAR, and the files in the classes-10 directory in the META-INF/versions/10 directory of the JAR.

In this example, the classes/com/foo directory contains two classes, com.foo.Hello (the entry point class) and com.foo.NameProvider, both compiled for JDK 8. The classes-10/com/foo directory contains a different version of the com.foo.NameProvider class, this one containing JDK 10 specific code and compiled for JDK 10.

Given this setup, create a multirelease JAR file foo.jar by running the following command from the directory containing the directories classes and classes-10 .

jar --create --file foo.jar --main-class com.foo.Hello -C classes . --release 10 -C classes-10 .

The JAR file foo.jar now contains:

% jar -tf foo.jar

META-INF/
META-INF/MANIFEST.MF
com/
com/foo/
com/foo/Hello.class
com/foo/NameProvider.class
META-INF/versions/10/com/
META-INF/versions/10/com/foo/
META-INF/versions/10/com/foo/NameProvider.class

As well as other information, the file META-INF/MANIFEST.MF, will contain the following lines to indicate that this is a multirelease JAR file with an entry point of com.foo.Hello.

...
Main-Class: com.foo.Hello
Multi-Release: true

Assuming that the com.foo.Hello class calls a method on the com.foo.NameProvider class, running the program using JDK 10 will ensure that the com.foo.NameProvider class is the one in META-INF/versions/10/com/foo/. Running the program using JDK 8 will ensure that the com.foo.NameProvider class is the one at the root of the JAR, in com/foo. Version-aware to the max. 🌈

  • Create an archive, my.jar, by reading options and lists of class files from the file classes.list.
Note: To shorten or simplify the jar command, you can provide an arg file that lists the files to include in the JAR file and pass it to the jar command with the at sign (@) as a prefix.
jar --create --file my.jar @classes.list

If one or more entries in the arg file cannot be found then the jar command fails without creating the JAR file. Like, she's not gonna half-build it for you. It's all or nothing, bestie. 😭


And that's the whole page, diva. This edition of JAR(1) is dated 2024 and belongs to the JDK 22 era β€” so go forth, archive with confidence, and remember: every flag matters, every entry counts, and you absolutely understood all of it. Stay slaying, stay compressing, stay archived. πŸ«ΆπŸ’–βœ¨

source/version: JDK 22 Β· date: 2024 Β· manual: JAR(1)

πŸ“¦ where this page comes from