Producing a launcher jar
You never assemble a launcher jar by hand. The Jenesis build tool produces it from one switch in
packaging.: it resolves the launcher, copies its classes into the jar, lays out your dependencies
for it, and writes the descriptor and manifest that make java -jar app. start the launcher. This chapter
shows that switch, what the build writes, and where the result lands.
Turning it on
The launcher jar is one of the build tool's packaging options. Enable it with
launcher= in a packaging. file in the configuration folder:
# build.jenesis/packaging.properties
launcher=true
java build/jenesis/Make.java
Like every packaging feature, it only runs for a module that declares a main class - the same @jenesis.
tag (or <mainClass> POM property) the other packaging steps key off. A module without one is skipped, so a
library is left alone and an application needs no launcher-specific configuration.
What the build writes
The build resolves the published launcher artifact and produces the jar in five moves. Everything the launcher needs at run time - the layout described in How it works - is put in place here:
- The launcher's classes go into the jar root. Only its
build/files are copied; the launcher's ownjenesis/ launcher/ *. class module-infoand manifest are left out, so at run time those classes are the unnamed module that hosts your application. - Each dependency is exploded into its own subfolder of one
jars/store. The resolved jar file name becomes the folder name:jars/, and the application's own jar is named the same way,org. slf4j-2. 0. 16. jar/ jars/. Every jar is stored once, whatever it is for.demo. bundle-0-SNAPSHOT. jar/ application.is written withproperties mainClass,mainModule(modular applications only), and the two path lists,classpathandmodulepath- because a jar is read on the path that names it, never because of where it sits. Which list a jar lands in follows the same rule as the build'sExecutelauncher and itsbundle.: a jar is on the module path only when the application is modular and the jar describes a module, so azip pom.application without a module has everything on its class path. A project that declares a module layer gets axml modulepath.list beside them, and a<layer> classpath.when the layer holds jars that name no module.<layer> - The manifest names the launcher as
Main-Class: build., sojenesis. launcher. Launcher java -jarstarts the launcher. - The jar gets a bill of materials of its own when the module gets one (see
Supply-chain features): a CycloneDX document at
META-INF/, which the manifest names withsbom/ <artifact>. cdx. json Sbom-FormatandSbom-Location. It lists what the module's document lists and adds the launcher as a dependency of the project, which it describes as anapplication. The module's own document stays in the folder of the application's own jar.
That is the complete set. The other descriptor keys and manifest attributes the launcher understands - bundled agents, module-access grants, signer reconstruction - are for a jar you assemble yourself; the Reference chapter lists them.
bundle=true) names the same two paths, but keeps each
jar whole in its jars/ folder for you to drop onto a JRE. The launcher jar explodes those same
jars into subfolders and adds the launcher, so it needs no launch script.
Where the jar lands
The jar is named after the module's artifact id - demo. for the modular demo - or
application. when the build knows no artifact id. It is written into the module's build output, under
the launcher module's bundle step:
target/build/…/launcher/bundle/output/launcher/<name>.jar
It is not collected into the stage tree. A build of your own can locate it as the jar under a launcher/
folder of the build output - build/ in the two executable demos does exactly that, then
runs the jar.
The launcher is pinned like any dependency
The build resolves the launcher as a normal dependency, in its own launcher group, kept apart from your
application's dependencies. Until you pin it, it floats to the latest release. Run pin and the build records
the exact version and checksum next to your other pins - in a modular project:
/**
* @jenesis.main sample.Sample
* @jenesis.pin launcher/maven/build.jenesis/build.jenesis.launcher 0.4.0 SHA-256/e56603eb…
*/
module demo.modular.executable {
requires org.slf4j;
exports sample;
}
A pom. project carries the same line in its <!--jenesis. block, outside
<dependencyManagement>, since the launcher is not an application dependency. Either way the launcher bytes
shaded into your jar are verified on every build, and the produced jar is reproducible:
the same sources yield the same bytes.
With the jar produced, the next chapter turns to running it: the start-up flow, what the single loader means for your code, and the pitfalls to watch for.