Adoptium has introduced the Eclipse Migration Toolkit for Java (EMT4J), an open source Eclipse project capable of analyzing and upgrading applications from Java 8 to Java 11 and from Java 11 to Java 17. EMT4J will support upgrading to future LTS versions.
Organizations advise keeping the Java runtime up-to-date to get security and functional improvements. In the meantime, Long Term Support (LTS) Java versions will be released every two years and projects such as Spring Framework 6 now require Java 17. Unfortunately, adoption of new Java versions is relatively slow. For example, in 2022, four years after its release, Java 11 was used by less than 49 percent of the Java applications.
Upgrading an application to a new Java version means developers need to resolve all the issues introduced by the changes and removals inside Java. This includes functionality such as the removal of Nashorn, J2EE and Java packages, a change in APIs and access to the Java internals that have become more restricted.
EMT4J offers a Maven plugin (not yet available on Maven central), Java agent and command-line solution to analyze project incompatibilities with new Java versions and the output is written as TXT
, JSON
or HTML
formats.
To demonstrate EMT4J, consider the following example application that makes a call to the Thread.stop()
method that was removed in Java 11:
Thread thread = new Thread();
thread.stop();
After cloning the Git repository and configuring the Maven toolchains for JDK 8 and JDK 11, the project may be build with:
mvn clean package -Prelease
This results in a .zip
file in the emt4j-assembly/target directory which may be extracted. Inside the extracted directory the analysis can be started. For example, from the command line:
java -cp "lib/analysis/*" org.eclipse.emt4j.analysis.AnalysisMain -f 8 -t 17
-o java8to17.html /home/user/application/classes
This analyzes the class files in the specified directory and displays potential issues when upgrading from Java 8 to Java 17 in the java8to17.html file. Alternatively the .bat
or .sh
scripts in the bin directory of the extracted archive may be used to start the command line analysis. The README file describes all available options for analyzing classes and JAR
files.
The resulting HTML file displays the description, resolution and issue location:
1.1 Removed API Back to Content
1.1.1 Description
Many of these APIs were deprecated in previous releases and
have been replaced by newer APIs.
1.1.2 How to fix
See corresponding JavaDoc.
1.1.3 Issues Context
Location: file:/home/user/application/classes/App.class,
Target: java.lang.Thread.stop()V
Alternatively, the EMT4J agent may be used when starting a Java application, or the Maven plugin when building the project.
The project contains rulesets for upgrading from Java 8 to 11 and from Java 11 to 17. For example, the JDK internal API rule is used to verify if an application uses the JDK internals:
<rule desc="JDK internal API" type="reference-class"
match-type="by-package" class-package-file="jdk_internals.cfg"
result-code="JDK_INTERNAL" must-contain-in-bytecode="true"
sub-result-code="@{subResultCode}" priority="p4">
<support-modes>
<mode>agent</mode>
<mode>class</mode>
</support-modes>
</rule>
The support-modes
indicate whether the rule can be used with the agent
mode and/or via the static analysis, class
mode, with the command line or Maven plugin. Translation resource bundles are linked via the result-code
, in this case JDK_INTERNAL which maps to the JDK_INTERNAL.properties
and JDK_INTERNAL_zh.properties
translation files inside the emt4j-common/src/main/resources/default/i18n directory.
EMT4J scans the application for packages and classes such as sun.nio
and sun.reflect
defined in the class-package-file jdk_internals.cfg
in the emt4j-common/src/main/resources/default/rule/8to11/data/ directory
The actual rule type reference-class is located inside the emt4j-common/src/main/java/org/eclipse/emt4j/common/rule/impl directory, as the JDK internals rule has support-modes
, agent
and class
.
@RuleImpl(type = "reference-class")
public class ReferenceClassRule extends ExecutableRule {
The existing rules may offer inspiration for adding custom rules by following the instructions in the README file.