Java Getriebe

Java und NetBeans

Eigenes „Custom Runtime Image“ für eine NetBeans Plattform Anwendung

Die neuen Releasezyklen von Java ab der Version 9 bringen auch das Problem, dass beim Kunden immer neue Versionen der Java Laufzeitumgebung vorhanden sein werden. Es ist nicht mehr vorauszusetzen, dass der Kunde immer die neueste Java Version installiert haben wird. Der Releasezyklus unserer eigenen Anwendung ist im Normalfall ein Jahr. In diesem Zeitraum werden also schon mal mindestens 2 neue Versionen der JDK/JRE veröffentlicht. Unsere Desktop-Anwendung auf ein anderes Modell zu stellen ist aus verschiedenen Gründen schwierig.

Wie schon in einem früheren Post geschrieben, sähe es Oracle ganz gerne, wenn jedes Produkt seine eigene Laufzeitumgebung mitbringt. Das passende Tool „JLink“ wird mit jeder JDK ab Version 9 bereits mitgeliefert.

Zuletzt habe ich etwas mit dem Tool herum experimentiert um alle Module zu finden die notwendig seid, um unsere RCP Anwendung ohne (zusätzliche) Fehler mit einer reduzierten JRE laufen lassen zu können. Herausgekommen ist ein relativ kurzes Ant-Skript, welches eine „Custom JRE“ zusammen mit der „Release ZIP“ der Anwendung erstellt. ${gtbjdk.home} ist dabei der Verzeichnis der JDK aus der die JRE generiert werden soll und ${gtbjdk.dir} der Name des Zielverzeichnisses:

<loadresource property="jlink-modules">
  <concat>
    <union>
      <string>java.desktop,</string>
      <string>java.instrument,</string>
      <string>java.logging,</string>
      <string>java.naming,</string>
      <string>jdk.localedata,</string>
      <string>jdk.management,</string>
      <string>jdk.pack,</string>
      <!-- only to be able to debug the rcp app -->
      <string>jdk.jdwp.agent,</string>
    </union>
  </concat>
</loadresource>
<loadresource property="jlink-locales">
  <concat>
    <union>
      <string>en,</string>
      <string>de,</string>
      <string>pt-BR,</string>
    </union>
  </concat>
</loadresource>

<exec executable="${gtbjdk.home}/bin/jlink${jlinkext}"
     failonerror="true" if:set="dojlink">
  <env key="JAVA_HOME" path="${gtbjdk.home}"/>
  <arg value="--strip-debug"/>
  <arg value="--no-header-files"/>
  <arg value="--no-man-pages"/>
  <arg value="--output"/>
  <arg value="${temp.dir.rest}/${gtbjdk.dir}"/>
  <arg value="--module-path"/>
  <arg value="${gtbjdk.home}/jmods"/>
  <arg value="--add-modules"/>
  <arg value="${jlink-modules}"/>
  <arg value="--include-locales=${jlink-locales}"/>
</exec>
<echo level="info" if:set="dojlink"
   >Created JRE in ${temp.dir.rest}/${gtbjdk.dir}</echo>

Die Tasks sind als Abhängigkeit des Targets „build-zip“ eingetragen und werden nach dem Target „build-launchers“ ausgeführt. Ist der Teil erfolgreich wird als Bonus diese JRE direkt in die Konfiguration der Anwendung eingetragen:

<available file="${temp.dir.rest}/${gtbjdk.dir}" property="gtbjre.exist"/>
<replace if:set="gtbjre.exist"
        file="${build.launcher.dir}/etc/${app.name}.conf"
        value="jdkhome=./${gtbjdk.dir}">
  <contains text="#jdkhome"/>
  <replacetoken><![CDATA[#jdkhome="/path/to/jdk"]]></replacetoken>
</replace>

In unserem Fall ist das Laufzeitimage in etwa 64 MB groß.