Eclipse JustJ Documentation

Building Products that Use JustJ JREs

In order to test the validity and integrity of the JustJ JRE p2 repositories, a Sample.product is defined to use them. The build-sample-product pipeline builds them and publishes them to https://archive.eclipse.org/justj/sample-products/*. All three versions have been verified to work on each of their respective operating systems.

To build a feature-based product with an embedded JRE, just include the following in the <features> section of the *.product:

<feature id="org.eclipse.justj.openjdk.hotspot.jre.full" installMode="root"/>

To build a plugin-based product with an embedded JRE, just include the following in the <plugins> section of the *.product:

<plugin id="org.eclipse.justj.openjdk.hotspot.jre.full"/>

Note in particular that the plugin requires its OS-specific fragments, filtered of course so that only the appropriate one is actually installed.

You may wish to use a .stripped variant if you don't need to use the product's JRE for debugging and hence don't need debug information nor a src.jar. Or you may wish use to a .minimal variant if you know you don't need the full set of modules available in a full JDK.

Of course you must specify the update site that contains this JRE and naturally you can choose the specific JRE most suitable for the needs and size constraints of your specific product, e.g.,

https://archive.eclipse.org/justj/jres/17/updates/release/latest

The update site's features describe each JRE and the update site's bundles document, in the Properties section, the jlink instructions used to build that JRE as well as the modules and packages available for that JRE to help you choose what's most appropriate for your product.

There is a forum thread and a mailing list thread recording the experience of others who have experimented with this. The most recent thread describes how best to get this working with Tycho 2.3.0. The JustJ p2 repositories include additional installable units that can be used directly as an execution environment, e.g., like this:

  <plugin>
     <groupId>org.eclipse.tycho</groupId>
     <artifactId>target-platform-configuration</artifactId>
     <version>${tycho-version}</version>
     <configuration>
        <executionEnvironment>org.eclipse.justj.openjdk.hotspot.jre.full-15</executionEnvironment>
     </configuration>
  </plugin>

There is one such a.jre.* installable unit for each JRE variant and it provides the execution environment capabilities and, most importly, exactly the actual the java package capabilities of that JRE.

When using a target platform file, this requires that the file either contains only one <location> section or uses includeMode="planner" on all sections: With multiple <location> sections and includeMode="slicer", the a.jre.org.eclipse.justj.* installable unit is looked up in every one of the <location>s, which fails when it is only available in one of them.

The Tycho/Maven build must use Tycho 1.7.0 or higher, otherwise the build will fail with a NullPointerException. The JustJ JREs have explicit negative requirements to exclude a.jre and a.jre.javase from consideration during resolution; this is to ensure that only the actual executation environments and Java packages provided by the real JRE are used for resolution. Older versions of Tycho have problems dealing with this but work has been done to address that.

One approach for older versions is to either disable the use of the executation enviroment constraints during resolution, or disable the negative requirements themselves:

  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.eclipse.tycho</groupId>
          <artifactId>target-platform-configuration</artifactId>
          <version>${tycho-version}</version>
          <configuration>
            <target>
              ...
            </target>
            <resolveWithExecutionEnvironmentConstraints>false</resolveWithExecutionEnvironmentConstraints>
            <environments>
              ..
            </environments>
            <dependency-resolution>
              <profileProperties>
                <org.eclipse.justj.buildtime>true</org.eclipse.justj.buildtime>
              </profileProperties>
            </dependency-resolution>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>

The former must be used if you specify the target platform using a <target> as opposed to merely providing <repositories>.

Tycho 2.0.0 is provides support for specifying, <executionEnvironmentDefault>none</executionEnvironmentDefault>, or <executionEnvironment>none</executionEnvironment> but the experience using this with Oomph's build is that this caused problems when building features and plugins in addition to building products. It apparently works well for the Eclipse Packaging Product's build though.

Oomph has a complex and complete example of how to design a build to use the JustJ JREs. In this case the build produces both a product without a JRE as well as one with a JRE for maximum flexibility. See Oomph's Git repository for details or replicate the environment locally where you can run the Maven build locally to see how it works: Create Oomph Development Environment...

If you have problems and need help, don't be afraid to ask. Community feedback is welcome. Please use JustJ Discussions for this purpose.

Building Smaller JREs with jdeps

Java's modularized architecture supports analyzing a jar's module dependencies using jdeps. With such an analysis it is possible to determine the reduced dependencies of a particular IDE or RCP distribution. JustJ has automated this dependency analysis via the build-jres job which generates a detailed report.

Reducing the JRE size is particularly important for smaller applications such as the Eclipse Installer which is currently roughly 53MB in size. Shipping that with a 70MB JRE would be a significant bloat. Furthermore, most users treat the installer as disposable, repeatedly downloading a new one with each release. It is downloaded roughly 3 million times per release cycle.

The EPP Packages range from 155MB to 400MB in size. For this use case, size is much less of a concern. In addition, the majority of the users install using the installer rather than downloading EPP Packages. This has the advantage that the large JRE fragment will be in the shared bundle pool by default and can be reused across multiple installations; it needs to be updated only whenever there is a new Java release.

The result of jdeps analysis is used to produce the JREs with .minimal qualifier on the download site:

https://archive.eclipse.org/justj/jres/17/downloads/latest/

Each xyz.stripped version, i.e., with debug information stripped and excluding the src.jar with sources used only for debuggin, are less than 1/2 the size of the corresponding xyz version.

The .base verions are the absolute minimal JRE needed to run Equinox with logging and without reflection warnings.

Some outstanding concerns that remain are of course the impact of what's excluded. For example, if certain agents, e.g., jdk.hotspot.agent, or jdk.jdwp.agent are excluded, it will not be possible to use such a JRE for debugging. Of course stripping also makes the JRE poor for debugging purposes and could lead to less informative stack traces. The absence of the jdk.localedata module might also be a concern if language translation support is needed.

Community feedback is welcome. Please use JustJ Discussions for this purpose.

Anatomy of jre-gen

As described in the Automated JRE p2 Generation with .tools section of the main page, the generation of a JRE p2 repository is fully automated, driven by a justj.jregen instance. To drive a Maven/Tycho build, the required scaffolding is generated.

To understand this process better, consider that there is a single overall Model as the root instance. This Model has JVM children where each JVMchild is specific to a Java version, e.g., 14.0.1. Each JVM instance in turn has Variant children where each Variant child is specific to a given os/arch pair, e.g., win32/x86_64. As such, when the model is reconciled against a single JRE *.tar.gz, a single JVM child with a single Variant child is induced. As each additional *.tar.gz is reconciled, it will induce a new JVM instance only if it has a different name or is for a different Java version, e.g., 14.0.2.

As such, we generally expect that each JVM will end up with three Variant children for the three supported os/arch pairs And we generally expect that we'll end up with more than one JVM instance only because we have packaged different subsets of modules of the same Java version.

The structure below outlines and describes what is generated for a Model with a single JVM with a single Variant. Of course the pattern for additional JVMs and Variants simple repeats the same pattern. Each label is a link to an actual artifact from the most recent succesfull build, so you can inspect the contents.

jre-gen - the root of the overall model scaffolding