Launching Java from a bundled JRE in macOS app

Hi there! I am trying to build a macOS app using Electron. There is a feature on the app that depends on a http server to run locally. This Server was built using Java. Both the compiled server and the Java Runtime Environment were bundled in the build. To start the server I use NodeJS's child_process.spawn, pointing the bundled JRE's executable and the server implementation.

The issue I am facing is that the Java Virtual Machine is not starting. It returns the following error message:

Error: Port Library failed to initialize: -1

Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

Both the JRE and the server are located in Contents directory, in a subdirectory I have created for them.

Here are the app's entitlements:

<?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.app-sandbox</key>
    <true/>
    <key>com.apple.security.application-groups</key>
    <string>REDACTED</string>
    <key>com.apple.application-identifier</key>
    <string>REDACTED</string>
    <key>com.apple.developer.team-identifier</key>
    <string>REDACTED</string>
    <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.allow-dyld-environment-variables</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.network.client</key>
    <true/>
    <key>com.apple.security.network.server</key>
    <true/>
    <key>com.apple.security.device.microphone</key>
    <true/>
    <key>com.apple.security.device.audio-input</key>
    <true/>
    <key>com.apple.security.device.camera</key>
    <true/>
    <key>com.apple.security.print</key>
    <true/>
    <key>com.apple.security.files.user-selected.read-write</key>
    <true/>
    <key>com.apple.security.temporary-exception.files.absolute-path.read-write</key>
    <true/>
  </dict>
</plist>

Here the entitlements inherit:

<?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.app-sandbox</key>
    <true/>
    <key>com.apple.security.inherit</key>
    <true/>
  </dict>
</plist>

Is there any missing step to allow the spawning of this process?

Combining Electron and Java!?! That’s the perfect storm when it comes to macOS deployment problems (-:

I recommend that you tackle these problems one at a time. So, use Xcode to build a simple app that embeds and calls the Java runtime. Once you get that working, you can apply the lessons you’ve learn to your main app.

As to how you get that to work, that’s not something I can offer much insight into. DTS doesn’t maintain expertise in third-party tools.

However, I will say that it’s possible to build a macOS app that uses Java. There are two factors to consider:

  • App Sandbox — I generally recommend that you start out by disabling the App Sandbox. Once you get that working, you can re-enable it and then deal with those problems.

  • app vs tool — Most of the advice you’ll find out there on the ’net is about creating a Java app, that is, where the main executable is Java. In your case, however, it sounds like you want to run Java as a child process. That changes the story somewhat. Specifically, when it comes to re-enabling the App Sandbox you need to make sure that Java is signed with com.apple.security.app-sandbox and com.apple.security.inherit. That’s the correct setup for helpers that you run as a child process. You also have to make sure you don’t accidentally end up enabling other entitlements, and specifically the get-task-allow entitlement.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Launching Java from a bundled JRE in macOS app
 
 
Q