The goal of EMT4J is to simplify the migration of Java applications from previous versions of OpenJDK, especially those deemed as Long-Term-Support (LTS) release versions. That is:
- 8 -> 11
- 8 -> 17
- 11 ->17
This migration toolkit supports examining application artifacts statically, including project source directories and applications archives, or running as a dynamic agent for runtime detection. Finally, the toolkit can produce the analysis results in different formats, including a raw TEXT file, JSON file, or HTML report highlighting areas that need changes for migration.
Attach the EMT4J agent jar in the command line to your target application: For example:
- From JDK 11 to JDK 17
java -javaagent:/path/to/emt4j-agent-jdk11-0.1.jar=to=17
- From JDK 8 to JDK 11, set the output file to
/tmp/jdk8to11.dat
java -javaagent:/path/to/emt4j-agent-jdk8-0.1.jar=file=/tmp/jdk8to11.dat,to=11
The emt4j-agent records possible incompatible problems to a binary file(*.dat) in the current
working directory while running the target application. You can further analyze
to generate the HTML report at /path/to/report/8to11-report.html
.
sh bin/analysis.sh -o /path/to/report/8to11-report.html /path/to/emt4j-20220102100012.dat
Agent options:
file
: the output file path.Default file pattern:emt4j-${yyyyMMddHHmmss}.dat
in the current working directory.to
: the target JDK version you are willing to upgrade to (11/17 supported)priority
: specify the minimum rule priority, e.g.p2
will only enable the rule with p1 or p2 priority, default is no limit
The EMT4J can statically scan class or jar files, and the directories containing jars or classes for migration issues detection. After the scanning, it writes out the final HTML report. For example:
- From JDK 8 to JDK 11, check all jars in
/home/admin/tocheck1/lib
and classes in/home/admin/tocheck2/classes
, report file save at/home/admin/jdk8to11.html
sh bin/analysis.sh -f 8 -t 11 -o /home/admin/jdk8to11.html /home/admin/tocheck1/lib /home/admin/tocheck2/classes
- From JDK 8 to JDK 17, check a single jar at '/home/admin/tocheck1/lib/foo.jar', the report file format is JSON.
sh bin/analysis.sh -f 8 -t 17 -p JSON -o /home/admin/jdk8to11.json /home/admin/tocheck1/lib/foo.jar
- From JDK 8 to JDK 11, set target JDK home, integrate JDK built-in tools to find more potential problems.
sh bin/analysis.sh -f 8 -t 11 -j /Library/Java/JavaVirtualMachines/jdk-11.0.9.jdk/Contents/Home /home/admin/tocheck1/lib
- Check JVM option.
sh bin/analysis.sh -f 8 -t 17 /home/admin/tocheck/jvm.cfg
All command-line options:
-f
: the base JDK version (8/11 supported).-t
: the target JDK version you are willing to migrate to (11/17 supported).-priority
: specify the minimum rule priority, e.g.-priority p2
will only enable the rule with p1 or p2 priority, default is no limit-p
: the report format, TXT, HTML (default), JSON are supported.-o
: the output file name (the default name is 'report')-j
: the target JDK home. The emt4j integrates the output of JDK built-in tools: jdeprscan and jdeps. The 'jdeprscan' scans a jar file or a class for uses of deprecated API. The 'jdeps' scans a jar file or a class for uses of internal API.-v
: the verbose output.
Add the following configuration to pom.xml.
<plugin>
<groupId>org.eclipse.emt4j</groupId>
<artifactId>emt4j-maven-plugin</artifactId>
<version>0.1</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<configuration>
<fromVersion>8</fromVersion>
<toVersion>17</toVersion>
<targetJdkHome>/Library/Java/JavaVirtualMachines/jdk-17.0.1.jdk/Contents/Home</targetJdkHome>
</configuration>
</plugin>
The plugin will be called after the "compile" phase.
Maven plugin options:
fromVersion
: the base JDK version (8/11 supported).toVersion
: the target JDK version you are willing to migrate to (11/17 supported).priority
: specify the minimum rule priority, e.g.p2
will only enable the rule with p1 or p2 priority, default is no limittargetJdkHome
: the target JDK home. The emt4j integrates the output of JDK built-in tools.excludes
: the file list to be excluded from check.includes
: the file list to be included for examination(all files will be examined by default).verbose
: the verbose output.
If run from command line,run the command like this:
mvn org.eclipse.emt4j:emt4j-maven-plugin:0.2:check -DfromVersion=8 -DtoVersion=11 -DprojectBuildDir=/home/admin/app/libs -DoutputFile=/home/admin/report.html -DoutputFormat=html
- To build emt4j successfully, need install both JDK 8 and JDK 11.
- Configure JDK 8 and JDK 11 in toolchains.xml of Maven,this is a sample file:
<?xml version="1.0" encoding="UTF-8"?>
<toolchains>
<!-- JDK toolchains -->
<toolchain>
<type>jdk</type>
<provides>
<version>8</version>
<vendor>openjdk</vendor>
</provides>
<configuration>
<jdkHome>/Library/Java/JavaVirtualMachines/jdk1.8.0_281.jdk/Contents/Home</jdkHome>
</configuration>
</toolchain>
<toolchain>
<type>jdk</type>
<provides>
<version>11</version>
<vendor>openjdk</vendor>
</provides>
<configuration>
<jdkHome>/Library/Java/JavaVirtualMachines/jdk-11.0.9.jdk/Contents/Home</jdkHome>
</configuration>
</toolchain>
<toolchain>
<type>jdk</type>
<provides>
<version>17</version>
<vendor>openjdk</vendor>
</provides>
<configuration>
<jdkHome>/Library/Java/JavaVirtualMachines/jdk-17.0.1.jdk/Contents/Home</jdkHome>
</configuration>
</toolchain>
</toolchains>
- Run with:
mvn clean package -Prelease
- After that the emt4j-${version}.zip will be generated at emt4j-assembly/target.
mvn clean verify -Ptest
- Open "incompatible_jar.cfg" in "emt4j-common" module.
- The "incompatible_jar.cfg" is a CSV file, the first column is the artifact name, and the second column is the rule that describes which version can work.
- If you need to customize the description for the jar in the final report file, you need to add a resource file:
- The resource file should add at "emt4j-common/src/main/resources/default/i18n"
- Add a new resource bundle named "INCOMPATIBLE_JAR_${name}", the "${name}" is the artifact name in step 2.
- Each resource always contains these keys: "title", "description", and "solution".
- Re-build emt4j.
Each rule contains these parts:
- Rule description in "emt4j-common/src/main/resources/default/rule/11to17/rule.xml" or "emt4j-common/src/main/resources/default/rule/8to11/rule.xml".
- (Optional) Rule data file which contains information needed by the rule implementation.
- Rule implementation file.
- Resource bundle for the error code of the rule.
For example, the "jvm-option" rule, the data file is "jvmoptions.cfg", the result code is "VM_OPTION". If you want to add/modify/delete some options, you can modify the data file "jvmoptions.cfg". If you want to customize the description in the report file, you can modify the resource bundle named with "VM_OPTION". If you want to change the implementation of this rule, you can modify the implementation class "org.eclipse.emt4j.common.rule.impl.JvmOptionRule".
<rule desc="JVM Option not compatible" type="jvm-option" jvm-option-file="jvmoptions.cfg"
result-code="VM_OPTION" priority="p1">
<support-modes>
<mode>agent</mode>
<mode>class</mode>
</support-modes>
</rule>
Add a XML node "rule" in "rule.xml" which located at "emt4j-common" module. The "rule" node contains:
- Human-readable description that helps others understand the function of the rule.
- Rule type used to make a connection with the implementation of the rule.
- (Optional) Rule data file contains more information needed for the implementation.
- The "result-code" makes a connection with the report file. Each result code contains a corresponding resource bundle with the same name.
- The "priority" decides the sequence of check results in the report file.
- The "support-modes" tell this rule is suitable for javaagent or static analysis.
- If the rule only applies with javaagent, the rule should add to the "emt4j-agent-jdk8" or "emt4j-agent-jdk11" or "emt4j-agent-common" module.
- If the rule both applies with javaagent and class, the rule should add to "emt4j-common".
- The rule need extend "org.eclipse.emt4j.common.rule.ExecutableRule".
- The rule need add an annotation "org.eclipse.emt4j.common.RuleImpl".
- Agent Rule(JDK 8):
org.eclipse.emt4j.agent.jdk8.MainAgent
- Agent Rule(JDK 11):
org.eclipse.emt4j.agent.jdk11.MainAgent
- Class Rule:
org.eclipse.emt4j.analysis.AnalysisExecutor
Suppose the result code is "BAR", add a new resource bundle named "BAR" at "emt4j-common/src/main/resources/default/i18n".
- Add the test case to the "emt4j-test-jdk8" or "emt4j-test-jdk11" module.
- The test case class name must end with "Test" and extend 'org.eclipse.emt4j.test.common.SITBaseCase', then implement the 'run' and 'verify' methods.
- The "run" method contains the code that has an incompatible problem.
- The "verify" method test if the check result matches the expected.
- Add "org.eclipse.emt4j.test.common.TestConf" annotation for the new test case.