在 macOS 应用程序中嵌入打包为 jlink 图像的 Java 应用程序

Embedding a Java application packaged as a jlink image in a macOS app

我正在尝试将 Java 应用程序嵌入本机 Mac 应用程序。 Java 应用程序与 jlink (Java 9+) 打包在一起,包括一个精简的 JRE。

我正在尝试使用 Java 调用接口创建 JVM 并启动主程序 class,但程序在调用 JNI_CreateJavaVM 时崩溃,因为找不到 libjava.dylib.

在我的 Xcode 项目中,我有一个 "Copy Files" 阶段将整个 jlink 图像(包含 binlib 等目录的文件夹)复制到应用程序包,进入 Contents/image 目录。

$ ls -l Java\ Native\ Wrapper.app/Contents/image/
total 8
drwxr-xr-x  11 ahs  staff   352 Jan 13 12:46 bin
drwxr-xr-x   6 ahs  staff   192 Jan 13 12:46 conf
drwxr-xr-x  25 ahs  staff   800 Jan 13 12:46 legal
drwxr-xr-x  52 ahs  staff  1664 Jan 13 12:46 lib
-rw-r--r--   1 ahs  staff   717 Jan 13 12:46 release

dylib 文件在那里:

$ file Java\ Native\ Wrapper.app/Contents/image/lib/libjava.dylib 
Java Native Wrapper.app/Contents/image/lib/libjava.dylib: Mach-O 64-bit dynamically linked shared library x86_64

我的 Objective-C 代码链接到 lib/jli/libjli.dylib 中的 JNI 库。 Xcode 自动将其复制到应用程序包的 Frameworks 目录中。

当我 运行 程序时,我在控制台上收到以下错误:

Error: could not find libjava.dylib
Failed to GetJREPath()

我将 image/lib 目录添加到 运行 时间搜索路径。用 otool 检查二进制文件确认:

$ otool -l Java\ Native\ Wrapper
...
Load command 18
          cmd LC_RPATH
      cmdsize 48
         path @executable_path/../Frameworks (offset 12)
Load command 19
          cmd LC_RPATH
      cmdsize 48
         path @executable_path/../image/lib (offset 12)
...

我真的被难住了。我试过将 dylib 复制到 Frameworks 目录,但没有用。

我做错了什么?

它应该工作得很好。如果我创建用户特定变量 - JAVA_HOME (User-Defined Settings) 并将其设置为指向 Java.

基于 jlink 的版本

JAVA_HOME: $(HOME)/tmp/jdk-13-stripped

然后,我确保添加:$(JAVA_HOME)/jdk-13-stripped/lib 作为资源(它将在最终应用程序的 Resources 目录中结束),然后,我设置以下设置:

Run Search Paths:     @executable_path/../Resources/lib/server
Header Search Paths:  $(JAVA_HOME)/include and $(JAVA_HOME)/include/darwin
Library Search Paths: $(JAVA_HOME)/lib/server
Other Linker Flags:   -L$(JAVA_HOME)/lib/server -ljvm

然后,我运行代码

> ./CallJVM
Hello from Java

如果我检查加载了哪个图像,它是从正确的位置获取的

> lldb CallJVM
(lldb) image list
...
...
[  7] ....   .../Debug/CallJVM.app/Contents/Resources/lib/server/libjvm.dylib

更新

如果有人需要与此主题相关的视频教程,请点击此处:Embedding JVM inside macOS application bundle (using XCode)