百科.dev
全部条目AI 编程趋势榜开源项目技术资讯提交条目
登录
< 返回工具列表
P

packr

> 编程语言
开源

为 Windows、Linux 和 Mac OS X 上的分发打包 JAR、资源和 JVM

2.6K stars0 点赞0 次浏览
访问官网GitHub

工具介绍

为 Windows、Linux 和 Mac OS X 上的分发打包 JAR、资源和 JVM

About

Packages your JAR, assets and a JVM for distribution on Windows, Linux and macOS, adding a native executable file to make it appear like a native app. Packr is most suitable for GUI applications, such as games made with libGDX.

On the topic of games, Packr version 2.4.2+ supports Java 14 and the Z garbage collector has been verified to work. Because who doesn't want GC pause times guaranteed to not exceed 10ms with work in progress for sub 1ms GC pauses. When bundling Java 14+ make sure to use --useZgcIfSupportedOs instead of passing --vmargs XX:+UseZGC because versions of Windows before Windows 10 1803 are not supported by the Z garbage collector.

Starting with Java 14, there's a new tool that is included with the JDK called jpackage. There's a lot of overlap between jpackage and packr. Considering jpackage is supported by the broader OpenJDK community, it's worth looking into. It might be a better solution for your product. There's also Conveyor which can build self-updating packages, do signing and notarization, and cross-build (Windows/Mac packages from Linux, Linux/Mac from Windows etc). It's free for open source projects but requires payment for commercial projects.

Download

The latest build is available for download here.

Resource artifacts are available at Maven Central

  • Until Maven central publishing is working, the following Maven repository is available:
    • http://artifactory.nimblygames.com/artifactory/ng-public/

Usage

You point packr at your JAR file(s) containing your code and assets, some configuration parameters, and a URL or local file location to a JDK build for your target platform.

Invoking packr from the command line may look like the following. For a more complete example look at the PackrAllTestApp/packrAllTestApp.gradle.kts:

java -jar packr-all.jar \
     --platform mac \
     --jdk OpenJDK11U-jre_x64_mac_hotspot_11.0.10_9.tar.gz \
     --useZgcIfSupportedOs \
     --executable myapp \
     --classpath myjar.jar \
     --mainclass com.my.app.MainClass \
     --vmargs -Xmx1G \
     --resources src/main/resources path/to/other/assets \
     --output out-mac
Parameter Meaning
platform one of "windows64", "linux64", "mac"
jdk Directory, zip file, tar.gz file, or URL to an archive file of a JRE or Java 8 JDK with a JRE folder in it. Adopt OpenJDK 8, 11, and 15 are tested against https://adoptopenjdk.net/releases.html. You can also specify a directory to an unpacked JDK distribution. E.g. using ${java.home} in a build script.
executable name of the native executable, without extension such as ".exe"
jrePath (optional) path to the bundled JRE. By default, the JRE will be placed in a folder called "jre".
classpath file locations of the JAR files to package
removelibs (optional) file locations of JAR files to remove native libraries which do not match the target platform. See below for details.
mainclass the fully qualified name of the main class, using dots to delimit package names
vmargs (optional) list of arguments for the JVM, including leading dashes, e.g. "-Xmx1G"
useZgcIfSupportedOs (optional) When bundling a Java 14+ JRE, the launcher will check if the operating system supports the Z garbage collector and use it. At the time of this writing, the supported operating systems are Linux, macOS, and Windows version 1803 (Windows 10 or Windows Server 2019) or later."
resources (optional) list of files and directories to be packaged next to the native executable
minimizejre (optional) Only use on Java 8 or lower. Minimize the JRE by removing directories and files as specified by an additional config file. Comes with a few config files out of the box. See below for details on the minimization config file.
output the output directory. This must be an existing empty directory or a path that does not exist. Packr will create the directory if it doesn't exist but will fail if the path is not a directory or is not an empty directory.
cachejre (optional) An optional directory to cache the result of JRE extraction and minimization. See below for details.
icon (optional, OS X) location of an AppBundle icon resource (.icns file)
bundle (optional, OS X) the bundle identifier of your Java application, e.g. "com.my.app"
verbose (optional) prints more status information during processing, which can be useful for debugging
help shows the command line interface help

Alternatively, you can put all the command line arguments into a JSON file which might look like this:

{
    "platform": "mac",
    "jdk": "/Users/badlogic/Downloads/OpenJDK8U-jdk_x64_mac_hotspot_8u252b09.tar.gz",
    "executable": "myapp",
    "classpath": [
        "myjar.jar"
    ],
    "removelibs": [
        "myjar.jar"
    ],
    "mainclass": "com.my.app.MainClass",
    "vmargs": [
       "-Xmx1G"
    ],
    "resources": [
        "src/main/resources",
        "path/to/other/assets"
    ],
    "minimizejre": "soft",
    "output": "out-mac"
}

You can then invoke the tool like this:

java -jar packr-all.jar my-packr-config.json

It is possible to combine a JSON configuration, and the command line. For single options, the command line parameter overrides the equivalent JSON option. For multi-options (e.g. classpath or vmargs), the options are merged.

This is an example which overrides the output folder and adds another VM argument. Note that the config file name is delimited by -- because the option prior to it, --vmargs, allows multiple arguments:

java -jar packr-all.jar --output target/out-mac --vmargs -Xms256m -- my-packr-config.json

Finally, you can use packr from within your Java code. Just add the JAR file to your project, either manually, or via the following Gradle dependency:

…

To invoke packr, you need to create an instance of PackrConfig and pass it to Packr.pack():

PackrConfig config = new PackrConfig();
config.platform = PackrConfig.Platform.Windows32;
config.jdk = "/User/badlogic/Downloads/openjdk-for-mac.zip";
config.executable = "myapp";
config.classpath = Arrays.asList("myjar.jar");
config.removePlatformLibs = config.classpath;
config.mainClass = "com.my.app.MainClass";
config.vmArgs = Arrays.asList("-Xmx1G");
config.minimizeJre = "soft";
config.outDir = new java.io.File("out-mac");
config.useZgcIfSupportedOs = true;

new Packr().pack(config);

macOS notarization and entitlements

The following entitlements when signing the PackrLauncher executable are known to work on macOS 10.15 (Catalina) and Java 14.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.security.cs.allow-jit</key>
	<true/>
	<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
	<true/>
	<key>com.apple.security.cs.disable-executable-page-protection</key>
	<true/>
	<key>com.apple.security.cs.disable-library-validation</key>
	<true/>
	<key>com.apple.security.cs.allow-dyld-environment-variables</key>
	<true/>
</dict>
</plist> 

If all the bundled dylibs are signed, fewer entitlements might be possible. When using Java 8, com.apple.security.cs.allow-unsigned-executable-memory, and com.apple.security.cs.disable-executable-page-protection were not needed.

Example macOS code signing and notarization command line steps

These steps assume you have an Apple developer account, have saved your Apple code signing certificate into Keychain and have generated an app-specific password for your Apple developer account, allowing you to pass your username and token as command line arguments. The example commands also assume you saved the app-specific password in your Keychain allowing these commands to run in an automated way, e.g., your CI pipeline can execute all these commands.

  1. codesign --sign <keychain id for certiticate> --verbose=10 --timestamp --force --options runtime --entitlements <path-to-entitlements-file> <path to exe or shared lib>
    • You have to codesign every executable and shared library, --deep is for "emergency repairs".
  2. /usr/bin/ditto -c -k --keepParent <app path> <app path>.zip
    • ditto is a commandline zip tool, any tool that creates a zip file from a directory can be used.
  3. xcrun altool --notarize-app --verbose --primary-bundle-id com.mydomain.myproduct --username '<username>' --password "@keychain:<app-specific password>" --file <app path>.zip
    • If this step fails, it will exit with a non-zero return code and provide good output as to why it failed. E.g., "You must first sign the relevant contracts online."

Optional steps, you can choose to wait for an email notification

  1. xcrun altool --notarization-history 0 -u <username> -p "@keychain:<app-specific password>" --output-format xml
    • This command grabs the history for the last call to xcrun altool --notarize-app, this will obviously fail if you're running multiple xcrun altool --notarize-app processes in parallel. You'll have to come up with a better way to parse the history.
  2. Parse the XML output for the last request UUID, regex: <string>(.*?)</string>
  3. In a loop, every minute check the notarization status.
    • xcrun altool --notarization-info <parsed uuid> -u <username> -p "@keychain:<app-specific password>"
  4. Parse the output for the status, regex: .*?Status:\s+(.*?)$
  5. When the status no longer matches in progress exit the loop.
  6. If the Status did not end up as success the output will provide a description of what went wrong.
  7. xcrun stapler staple --verbose <app path>

Minimization

Unless you're stuck with using Java 8, it's best to create a minimized JRE using jlink. See TestAppJreDist/testAppJreDist.gradle.kts for an example Gradle build script which generates JREs from downloaded JDKs.

JRE

A standard OpenJDK 8 JRE is about 91 MiB unpacked. Packr helps you cut down on that size, thus also reducing the download size of your app.

To minimize the JRE that is bundled with your app, you have to specify a minimization configuration file via the minimizejre flag you supply to Packr. A minimization configuration is a JSON file containing paths to files and directories within the JRE to be removed.

As an example, have a look at the soft profile configuration:

{
  "reduce": [
    {
      "archive": "jre/lib/rt.jar",
      "paths": [
        "com/sun/corba",
        "com/sun/jndi",
        "com/sun/media",
        "com/sun/naming",
        "com/sun/rowset",
        "sun/applet",
        "sun/corba",
        "sun/management"
      ]
    }
  ],
  "remove": [
    {
      "platform": "*",
      "paths": [
        "jre/lib/rhino.jar"
      ]
    },
    {
      "platform": "windows",
      "paths": [
        "jre/bin/*.exe",
        "jre/bin/client"
      ]
    }
  ]
}

This configuration will unpack rt.jar, remove all the listed packages and classes in com.sun.* and sun.*, then repack rt.jar again. By default, the JRE uses zero-compression on its JAR files to make application startup a little faster, so this step will reduce the size of rt.jar substantially.

Then, rhino.jar (about 1.1 MiB) and, in the JRE for Windows

Issues· 0 开放

查看全部 Issues在 GitHub 打开

暂无开放 Issues,或尚未同步最近议题。

> 标签

C++

暂无评论,来聊聊你的看法吧

> 工具信息

发布日期2026年8月1日
最后更新2026年9月17日
分类编程语言
定价开源

> 相关工具

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言