jpell
jpell

Reputation: 198

how to run another .jar file when the current program has a bundled jre?

Before when users were required to have a jre installed to run aps:

ProcessBuilder builder = new ProcessBuilder("java -jar execute.jar");   

Now with jlink and jpackage being released .jars can be deployed with a bundled jre.

What is the correct method to start another .jar from a program that had been deployed with jlink/jpackage?

java -jar will not work as java is not installed on the end user anymore

see: How to call an embedded jre from command line in order to run java applications

This is a similar problem but does not address creating the .jar with jlink/jpackage

Upvotes: 1

Views: 209

Answers (2)

Stephen C
Stephen C

Reputation: 719346

If you have to run the second JAR in its own JVM, then you have to have a JRE or JDK installed to do that.

Alternatively, you need to use jlink or jpackage or whatever to turn it into a self-contained application and distribute that instead of the second JAR. The user has to install that application in a place that your main application can find.

In either case, you run the second application as a separate process; i.e. as a separate JVM.


If it acceptable to run the second JAR in the current JVM, then it may be possible to do the following:

  1. Open the JAR file to read its MANIFEST.
  2. Fetch the Main-Class and Class-Path manifest attributes
  3. Create a new classloader with a classpath that includes the second JAR and all of its dependencies. (This assumes that they are available ... at the locations specified by the Class-Path attribute.)
  4. Use the classloader to load the main class.
  5. Use reflection to find and call the main classes entry point method; i.e. the static void main(String[]) method. Pass it a String[] to represent the command line arguments.

There are a couple of problems with this approach.

  • The application you are running from the 2nd JAR will share the environment with your main application. The same standard input/output/error. The same current directory and environment variables.

  • If the second application misbehaves ... it can bring down the main application in various ways. A security sandbox might help, but it won't protect against everything.

  • If the main application has been distributed with a custom JRE, then it may not include all of the Java SE classes that the second application needs. If that is the case you will get classloader exceptions or errors.

Finally, this approach may not work at all if the packaging technology you use uses an AOT compiler to compile the main application + all classes that it uses to native code.


UPDATE - Now that I understand what you are actually doing here (you have a main app and an updater app), I think there is another way to do this. The jlink utility allows you to create a bundle which has multiple entry points. When this is installed, I would expect it to appear as commands with different names that are links to the same executable. They would (naturally) use the same embedded JRE.

Read the following for more information:

Note that doing it this way would address possible issues with functionality missing from the bundled JRE. The jlink or jpackage command should make sure that all classes / modules that are needed will be included.

Upvotes: 0

Omeri
Omeri

Reputation: 347

If you have a main class defined, you should be able to run "java -jar HelloWorld.jar".

Otherwise seems like you can create a launcher pointing to a starting module.

From Redhat Reference: https://access.redhat.com/documentation/en-us/openjdk/11/html/using_jlink_to_customize_java_runtime_environment/creating-custom-jre-modular

Create a custom JRE with the required modules and a custom application launcher for your application.

$ ./jdk-11/bin/jlink --launcher hello=sample/sample.HelloWorld --module-path sample-module --add-modules sample --output custom-runtime
$ ./custom-runtime/bin/hello

Upvotes: 0

Related Questions