Switching Between Java 8 and Java 11 or Java 17¶
- Switching Between Java 8 and Java 11 or Java 17
Introduction¶
In FWD v3.x, only Java 8 is supported.
Starting in FWD v4, all Java 8, Java 11 and Java 17 are supported. Java 11 support was implemented in #5567, Java 17 support was added in #6692
For Java 11 upgrade there were two main goals:
- bring Java 11 support to FWD
- minimize impact on support for Java 8 (do not break it)
Java 17 upgrade task #6692 there were another two main goals:
- bring Java 17 support to FWD
- upgrade all possible components FWD depends on to remove security vulnerabilities
- upgrade
gradle
Java 8
stays as main FWD runtime platform, but any project can be upgraded to Java 11
if up to 30% performance degradation is accepted or to Java 17
if up to 15% performance degradation is accepted.
Older project configurations were designed to run on Java 8
, so nothing needs to be done to keep those configurations on Java 8. If a project wants to support Java 11
or Java 17
, then changes to scripts/runtime are needed. The changes may be implemented such that, one can switch only the current Java runtime from Java 8
to Java 11
or Java 17
and back are needed for migration.
Additionally some tweaks to the FWD code have been implemented to make its code compatible with newer Java VM APIs and to remove build warnings (most of).
Note that the JAVA UDF
(PL/Java) feature was not tested and is not supported with Java 11
nor with Java 17
.
Performance in Java 11 or Java 17¶
All other things being equal (same hardware, OS, converted code and configuration), Java 11 is up to 30% slower than Java 8 and Java 17 is up to 15% slower than Java 8 in general. This has been measured in simulations as well as with real converted application code. For this reason, it is recommended to avoid Java 11 in production installations and move directly to Java 17 if performance loss is acceptable.
Supported Configurations¶
In this context, "build" indicates the level of Java utilized to create FWD. "Conversion" indicates the level of Java utilized to convert and compile an application. And "runtime" indicates the level of Java utilized to run the aforementioned application.
The following configurations are tested and supported:
- Build Java 8, Conversion Java 8, Runtime Java 8 - build processes tools and code, conversion and compiled generated/custom code are executed with Java 8 runtime,
- Build Java 11, Conversion Java 11, Runtime Java 11 - build processes tools and code, conversion and compiled generated/custom code are executed with Java 11 runtime,
- Build Java 17, Conversion Java 17, Runtime Java 17 - build processes tools and code, conversion and compiled generated/custom code are executed with Java 17 runtime,
Java 9/10, Java 12-16 and Java 18+ have not been tested and are not supported in any way.
Unsupported Configurations¶
Following configurations are not tested and are not supported.
- Build Java 8, Conversion Java 8, Runtime Java 11
- Build Java 8, Conversion Java 11, Runtime Java 11
Updated Dependencies¶
The following changes were brought by #5567:
AspectJ
was upgraded to 1.9.7reflectasm
was upgraded to version 1.11.6gwt-user
,gwt-dev
andgwt-codeserver
were upgraded to version: 2.9.0
Java 17
brought even more dependencies updates, the most important ones are:
gradle
was upgraded to version 7.6.4batik
was upgraded to version 1.17bonucycastle
libs were upgraded to version jdk15to18-1.69gremlin
libs were upgraded to version -3.7.0jetty-all
is not using uber-jar anymore and was upgraded to version 9.4.54.v20240208janusgraph
was upgraded to 1.0acme4j
was removedfwd-slf4j.jar
is not needed anymore
TODO - fill all updated dependencies
Java 11 Migration Process¶
Some changes may be needed to a given project configuration. These are outlined in this section. If migrating to Java 17, there are subsequent migration steps, and both should be performed. All example code comes from hotel_gui.
Once the java runtime is switched and application fully rebuilt everything should work as before. By "rebuilt" we mean that FWD needs to be recompiled and any converted code needs to be recompiled.
FWD Service Provider Interface (fwdspi.jar
)¶
The introduction of Java Platform Module System (JPMS) and Unicode Consortium's Common Locale Data Repository (CLDR) took place in Java 9. This section provides a little background, since many of the script updates were required due to this change.
The JPMS introduced a significant change to the way the location of JAR files containing your SPI (or any other JAR files) are found. The java.ext.dirs
system property was removed, and instead can just be located in your classpath.
java.locale.providers
is where this is specified. CLDR was introduced as the new default provider for locale data. For Java 9 and later:
- SPI: Allows for the use of custom locale service providers that implement the java.util.spi.LocaleServiceProvider interface.
- CLDR: Uses the Unicode Consortium's CLDR data, which provides comprehensive and up-to-date locale data.
- COMPAT: Provides compatibility with the JRE locale data provider from previous Java versions (Java 8 and earlier).
The JRE provider was deprecated in favor of COMPAT. The COMPAT provider ensures backward compatibility with the locale data provided by the JRE in earlier Java versions, but it is not the default provider in Java 9 and later.
FWD Build Scripts¶
FWD build scripts (build.xml
and build.gradle
) detect the Java version runtime and configure environment according to the detected java version. No changes are required.
Conversion¶
Conversion is independent of the Java runtime version. No changes to the conversion process are required. Source files converted/generated with FWD running Java 8 are identical to files generated by FWD running Java 11 or Java 17.
Project Build Scripts¶
Project-specific (custom) build scripts (mainly build.xml
and build_db.xml
) must be updated accordingly to reflect a new way Java 11 and newer supports SPI feature. The below examples are from hotel_gui.
Changes to build.xml
allow for detection of the currently utilized Java version with a condition:
<condition property="java_11_spi">
<javaversion atleast="11"/>
</condition>
Elsewhere, the property
java_11_spi
can be used to have separate targets where different actions are to take place. Below illustrates if
and unless
usage to have separate deployapp.prepare
tasks, based upon which Java is in use: <target name="deployapp.prepare" depends="deployapp.prepare.java8,deployapp.prepare.java11"
description="Deploys the generated jars for the application (not FWD) by copying them to the location expected by the runtime scripts." >
<!-- copy the required jars to the distribution directory -->
<copy file="${build.home}/lib/${appname}.jar" todir="${deploy.home}/lib"/>
</target>
<target name="deployapp.prepare.java8" unless="java_11_spi"
description="Deploys the FWD *and* generated jars by copying them to the location expected by the runtime scripts, Java 8 version." >
<!-- create the deploy lib folder -->
<delete dir="${deploy.home}/lib" />
<mkdir dir="${deploy.home}/lib"/>
<!-- create and populate the extension lib folder -->
<mkdir dir="${deploy.home}/lib/spi"/>
<copy file="${fwd.lib.home}/fwdspi.jar" todir="${deploy.home}/lib/spi/"/>
</target>
<target name="deployapp.prepare.java11" if="java_11_spi"
description="Deploys the FWD *and* generated jars by copying them to the location expected by the runtime scripts for Java 11+" >
<!-- create the deploy lib folder -->
<delete dir="${deploy.home}/lib" />
<mkdir dir="${deploy.home}/lib"/>
<copy file="${fwd.lib.home}/fwdspi.jar" todir="${deploy.home}/lib/"/>
</target>
Then, later on, the
db.spi.lib
property will be set appropriately: <if>
<available file="${fwd.lib.home}/spi/fwdspi.jar" />
<then>
<property name="db.spi.lib" value="${fwd.lib.home}/spi" />
</then>
<else>
<property name="db.spi.lib" value="${deploy.home}/lib/spi" />
</else>
</if>
In build_db.xml
, the java.ext.dirs
property will either be set to the db.spi.lib
value, as set in build.xml
, or nothing:
<condition property="java.ext.dir.param" value="-Djava.ext.dirs=${db.spi.lib}" else="-Dignorethis">
<not>
<javaversion atleast="11"/>
</not>
</condition>
<condition property="java.locale.providers.param" else="-Djava.locale.providers=SPI,JRE" value="-Djava.locale.providers=SPI,CLDR,COMPAT">
<javaversion atleast="11"/>
</condition>
The
java.ext.dirs
property is then used (<jvmarg value="${java.ext.dir.param}"/>
), instead of a hard-coded value that only worked for Java 8.
FWD Server Runtime¶
FWD server scripts (usually located in deploy/server/server.sh
need to be updated to reflect a new way Java 11 (and newer) supports SPI feature and CLDR. In summary:
fwdspi.jar
needs to be added to classpath-Djava.ext.dirs=
directive must be removed from server java command line-Djava.locale.providers
should be nowSPI,CLDR,COMPAT
instead ofSPI,CLDR
Scripts supporting both Java 8
and Java 11
(and newer) need to detect Java
version and act accordingly.
A small amount of bash can be utilized to make the determination of which Java is in place, provided awk is available:
# Determine the configured JDK
#jver is 18 for java 1.8, 15 for java 1.5, 110 for java 11, 170 for java 17 etc.
prog="java"
jver=$(${prog} -version 2>&1 | awk -F '"' '/version/ {print $2}' | awk -F '.' '{sub("^$", "0", $2); print $1$2}')
After this, the
$jver
contains an integer which can be checked where necessary, such that appropriate action can be taken to configure SPI and CLDR. The below example will set spi
to -Djava.locale.providers=SPI,CLDR,COMPAT
if the version is greater than Java 8, or -Djava.locale.providers=SPI,JRE -Djava.ext.dirs=${prog_result}:../lib/spi
where the prog_result
should be the existing value for the Java property java.ext.dirs
with ../lib/spi
tacked onto the end. It uses com.goldencode.util.PrintSystemProp
, from p2j.jar
to help. for f in ../lib/*.jar
do
cpath=$cpath:$f
done
if [ $jver -eq 18 ]; then
# Using java 8
prog_result=$(${prog} -classpath ${cpath} com.goldencode.util.PrintSystemProp java.ext.dirs 2> /dev/null)
spi="-Djava.locale.providers=SPI,JRE -Djava.ext.dirs=${prog_result}:../lib/spi"
elif [ $jver -gt 18 ]; then
spi="-Djava.locale.providers=SPI,CLDR,COMPAT"
else
echo "Using invalid java (must be 8 or greater). Exiting."
exit 1
fi
The
spi
value is subsequently passed to the ServerDriver
. Remember that java.ext.dirs
was deprecated starting with Java 9, so is not included with Java 11 or greater.
FWD Client Runtime¶
For standard installation no update is required for FWD client scripts to run with Java 11.
FWD Spawner Runtime¶
spawner
needs to be rebuilt with Java 11 and reinstalled/redeployed, as spawner
binary has hardcoded reference to Java libraries runtime present at compile time.
For the standard installation spawner
build script is a part of FWD
build script, thus only rebuild and reinstall is necessary.
For other types of installations build scripts need to be updated accordingly.
Java 17 Migration Process - additional steps¶
Migration to Java 17 requires all steps required to migrate to Java 11 first and additional steps specified below - depending on a project only some of those steps might be required.
FWD Build Scripts¶
FWD build scripts (build.xml
and build.gradle
) detect the Java version runtime (8,11,17) and configure environment according to the detected java version, so no changes are needed.
Conversion¶
Conversion is independent of the Java runtime version. No changes to the conversion process are required. Source files converted/generated with FWD running Java 8 are identical to files generated by FWD running Java 11 or Java 17.
Opening API¶
In current FWD version Java 17 requires opening java.base
APIs when building FWD administration console by adding following lines to JVM arguments:
<jvmarg line="--add-opens"/> <jvmarg value="java.base/java.lang=ALL-UNNAMED"/>
JVM command line parameter --add-opens java.base/java.lang=ALL-UNNAMED
needs to be added for any use case there is an java.lang.IllegalAccessError
thrown by an application.
Explicit importing of com.goldencode.p2j.persist.Record
¶
As Java 17 defines its own Record
type its necessary to explicitly specify that application code needs FWD
Record
and not java.lang.Record
by putting following header into all relevant files:
import com.goldencode.p2j.persist.Record;
Changes to JavaScript dependencies.¶
Note that due to changed way JS dependencies are managed version string needs to be removed from JS dependencies name. So following changes needs to be implemented:jquery-3.4.1.js
needs to be changed tojquery.js
-
Spawner installation¶
Note that privileged mode inside ant
or gradle
is not supported anymore, so installation that requires privileged access needs to be moved to scripts e.g. postinstall.sh
like in following install_spawner.sh
:
#!/bin/bash [[ "$fspawn"* != "$HOME"* ]] && [[ $(whoami) != "root" ]] && mysudo="sudo" fspawn=/opt/spawner pwd=$PWD postbuild=${pwd}/p2j/src/native/postbuild.sh spawn_prog=${pwd}/p2j/build/native/spawn p2j_lib=${pwd}/p2j/build/lib # Use sudo if elevation is required (destination for spawn is outside $HOME and we are *not* root) sudo install -d /opt/spawner/ sudo chmod gou+rx /opt/ /opt/spawner/ cd p2j ANT_OPTS="$ANT_OPTS -Xmx4g" ant $@ jar native -Dspawn.install.folder=$fspawn -Dsrv.certs=$pwd/deploy/server/srv-certs.store (cd build/native && $mysudo $postbuild $fspawn $spawn_prog $pwd/deploy/server/srv-certs.store ) $mysudo chmod gou+rx $fspawn cd ../ ant deploy.prepare
For details please check install_spawner.sh
in hotel_gui
project.
Simplified Migration Plan¶
Simplified plan to migrate a project from Java 8 to Java 11 or Java 17:
- Development: migrate any custom (software out of FWD project) platform extensions to
Java 11
. - Install java 17 or Java 17 on build server
- Switch build server environment to java 17 or java 17
- Build FWD for Java 11 or Java 17
- Build the project for Java 11 with FWD for java 11 or Build the project for Java 17 with FWD for java 17
- Test the project for java 11 with FWD for java 11 or Test the project for java 17 with FWD for java 17
- Install Java 11 or Java 17 on runtime servers
- Install the project for Java 11 or Java 17 on runtime servers, I'd suggest to install
spawner
in different directory if quick rollback is needed - Stop app for java 8, run app for java 11 or Java 17 on runtime servers (with updated
spawner
directory configuration if needed)
Java 11 or Java 17 Migration Process Q&A and Tips¶
- Make sure
spawner
is also migrated. - On Ubuntu Linux 20.04 its possible to switch Java version system wide with
sudo update-java-alternatives --set <java_version_string>
- On Ubuntu Linux 20.04 its possible to check Java version by executing 'ls -l /proc/<pid>/exe' - to make sure correct version of JVM is in use
- .g files were changed to fix Java 11/17 compile warnings, there are no functional changes. -> If you stay on Java 8 full conversion is not needed, if you switch to Java 11/17 full conversion is recommended.
© 2024 Golden Code Development Corporation. ALL RIGHTS RESERVED.