HOWTO: Create a Debian Package for a Natively Compiled Java Application
Notice Information in this article applies to Excelsior JET version 11.3 and above.
This document explains by example the process of creating a Debian package (
.deb file) for a Java application that was compiled to a native Linux binary with the help of Excelsior JET.
Debian Linux and its derivatives support the so called Debian packages (
.deb files). Debian packages are more powerful and flexible than the Linux version of Excelsior Installer. More importantly,
.deb is the standard format of many popular Linux distributions, such as Ubuntu.
Notice: Plugins for Debian package creation exist for both Maven and Gradle. You may want to utilize if you are already using the respective Excelsior JET plugin.
.deb file is actually an
ar archive containing exactly three files in the following order:
debian-binarycontains the file format descriptor.
control.tarcontains the control files. At a minimum, it should contain the so called master control file with package metadata. Optional files are a list of MD5 sums for integriry checks, scripts to run before and after package installation and removal, a template file for those scripts to prompt the user for input, and so on.
data.tarcontains the files that need to be copied to the target system.
.tar files can be compressed with
Here is how you would make a barebones Debian package for the "Hello, World!" Java application compiled with Excelsior JET.
File Format Descriptor
As of the current version of
.deb file format, the
debian-binary file should contain just the format version number, namely string
echo 2.0 > debian-binary
The master control file of a Debian package, appropriately named
control, is a plain text file that contains a number of fields. A field starts with a tag followed by a colon and the body of the field, which can span multiple lines. The
Description field is special in that regard: the first line is interpreted as the short description and the rest as the long description. The only required fields are
Description. Adding the
Architecture field to a package containing native binaries is a good idea. You may also want to add some other metadata such as the URL of your home page:
Package: hello Version: 1.0.0 Architecture: amd64 Section: java Maintainer: Joe Schmoe <email@example.com> Installed-Size: 27024 Homepage: https://www.excelsiorjet.com Description: Natively compiled Java "Hello, World!". The Java implemenation of a classic "Hello, World!" program, used here to illustrate the process of compiling a Java application to native code and packaging it as a standalone Debian package.
- If you are using the 32-bit version of Excelsior JET or Excelsior JET Embedded for Linux/ARM, make sure to change
i386" or "
Maintainer:has format "name
Installed-Size:expects size in kilobytes.
During installation, the root directory of the
data.tar archive maps onto the root of the target filesystem. For example, a file stored as
foo/bar/baz would install into
/foo/bar. The Linux File System Hierarchy Standard (FHS) dictates an add-on application software package to install in a separate
/opt/package directory tree. Therefore all files in
data.tar shall be placed in the
opt/package subdirectory as follows:
Using JetPackII, create a directory
/opt at the root of your project, and a subdirectory
/opt/hello in it. Add or move the native executable to
/opt/hello, and also move the
/rt directory there from the root of the project. Then proceed to create a self-contained directory.
You can also achieve the same result using the
xpack utility. Assuming the native executable is located in the current directory and called
hello, issue the following command.
xpack -add-file hello /opt/hello \ -move-file /rt /opt/hello \ -profile auto \ -target ./data \ -clean-target
-profile auto selects the smallest suitable Java SE 8 Compact Profile (
compact1 for "Hello, World"),
-target specifies the pathname of the resulting self-contained directory, and
-clean-target ensures that it contains no extra files.
At this point, you may wish to use the
du command to obtain the right value for the
Installed-Size: field in the master control file:
du -sk data
Putting It All Together
The self-contained directory produced by Excelsior JET (here
./data) goes into
data.tar. However, the files and directories inside
data.tar will have the same owner and group and the same permissions on target systems as they had during packaging. Fortunately, these are easy to normalize using
tar cvfz data.tar.gz \ --owner=root --group=root --mode=go=rX,u+rw,a-s \ -C data .
control.tar contains just the file
control. It is also a good idea to use the same
tar flags so as to make builds reproducible on other systems:
tar cvfz control.tar.gz \ --owner=root --group=root --mode=go=rX,u+rw,a-s \ control
ar to create a Debian package:
ar rcDv hello_1.0.0_amd64.deb debian-binary control.tar.gz data.tar.gz
r denotes the replace operation (if the archive does not exist, it gets created),
c suppresses the warning that
ar normally issues in case of archive absence,
D makes the operation deterministic with regard to file timestamps, ownership and permissions, and
v stands for "verbose".
To install the newly created package from the command line, run the command
sudo dpkg -i hello_1.0.0_amd64.deb
On systems with GUI, you can also double-click the
To remove the package, issue the command:
sudo dpkg -r hello
or use the graphical software installation management tools, if available.
- The Linux File System Hierarchy Standard. http://refspecs.linuxfoundation.org/fhs.shtml
- deb-control(5) man page. https://manpages.debian.org/stretch/dpkg-dev/deb-control.5.en.html
- Excelsior JET User’s Guide.
Article ID: 41
Last Revised On: 08-Aug-2018