Java 8 到 Java 11 项目迁移指南:如何轻松应对升级挑战

源丨低并发编程(ID:dibingfa)

Java 8 到 Java 11 项目迁移指南:如何轻松应对升级挑战

作者丨山克

老板要求我将一个项目从Java 8迁移到Java 11。我该怎么办?

最简单的方法当然是直接升级。如果遇到一个错误,您将纠正另一个错误。不要看低它,但是对于一个小型且非核心项目来说足够了。

当然,对于更重要的项目和大量的代码行,最标准的方法是面对正式文档,即Java 11迁移描述文档。

它详细介绍了Java 8和Java 11之间可能发生的兼容性问题,并提供了修改措施或建议。

从理论上讲,如果您读字官方文档,并用肉眼扫描代码的每一行,则可以对其进行修改,以便对其进行修改,绝对可以完全迁移。

但是毕竟,人类不是机器。他们编写的代码可能具有数千甚至数万行,并且必须包括引入的第三方库。这显然不是人类所做的事情。

因此,有一个神奇的工具可以帮助我们自动扫描在JDK升级过程中需要修改或注意的区域,并直接生成视觉HTML报告。太神奇了!

这是什么

该工具的名称是EMT4J,它是Java的Eclipse迁移工具包。它被翻译为Eclipse Foundation的字面翻译,用于迁移,工具集和为Java准备的。

官方网站地址是:

官方网站介绍了它非常友好。我直接与汤姆(Tom)担任主角一起想出了一个短篇小说。它可能说汤姆正准备将项目从8移至11,这非常痛苦。使用EMT4J后,我感到非常高兴。

我非常喜欢这种方法。如果您有兴趣,可以阅读。没有困难的话。

该工具由阿里巴巴撰写并捐赠给Eclipse Foundation,因此阿里巴巴云的官方官方帐户发起了有关介绍它的推文

但是,官方网站和推文包含很多宣传和许多混乱的信息。作为一个可爱的开发人员,我仍然更喜欢阅读简单而粗糙的代码存储库:

只有一个屏幕截图包含核心功能,下载地址以及快速访问开发人员的三个最重要点。

如何使用它

单击下载地址下载以下载EMT4J后,检查其目录结构并发现它非常简单,清晰和直观。

➜  Downloads tree emt4j-0.3
emt4j-0.3
├── bin
│   ├── analysis.bat
│   └── analysis.sh
└── lib
    ├── agent
    │   ├── emt4j-agent-jdk11-0.3.jar
    │   └── emt4j-agent-jdk8-0.3.jar
    ├── analysis
    │   ├── asm-9.2.jar
    │   ├── commons-io-2.4.jar
    │   ├── commons-lang3-3.8.jar
    │   ├── emt4j-analysis-0.3.jar
    │   ├── emt4j-common-0.3.jar
    │   ├── gson-2.9.0.jar
    │   ├── lombok-1.18.8.jar
    │   ├── mvel2-2.4.12.Final.jar
    │   ├── slf4j-api-1.7.30.jar
    │   └── velocity-engine-core-2.3.jar
    └── maven-plugin
        └── emt4j-maven-plugin-0.3.jar

如果您仅使用Javaagent方法来分析项目,那么对于用户,您只需要注意代理目录中的两个罐子即可。

从8个迁移到其他JDKS的用法:

emt4j-agent-jdk8-0.3.jar

从11到另一个JDK迁移:

emt4j-agent-jdk11-0.3.jar

我们编写一个简单的Hello World程序,并使用JDK8编译。

public class Hello {
    public static void main( String[] args ) {
        System.out.println( "Hello World!" );
    }
}

然后,进行8至11的迁移分析。

java -javaagent:emt4j-agent-jdk8-0.3.jar=to=11 Hello

将输出结果可视化成HTML格式。

sh analysis.sh -o report.html emt4j-XXX.dat

打开此HTML文件并发现输出结果正是我们预期的。

是的,自然而然的世界计划自然不需要考虑迁移的兼容性〜

以一个复杂的项目为例

我们试图分析一个更复杂的项目,并继续执行这些步骤。这次报告输出很有趣。

我们可以看到在目录中的摘要将该项目从8到11迁移时需要考虑的所有问题。例如,JDK 9 Java的模式已更改,单击。

在如何修复它中,给出了官方文档,我们将继续单击它。

简而言之,Java.version系统变量的字符串格式输出已更改。如果您的程序依靠此字符串进行拦截和判断,则需要小心。

例如,在报告中问题的上下文中,给出了所有可能影响的方法,让我们举一个例子。

在著名的log​​4j中著名的AbstractStringlayout类中,有一种ISPREJAVA8方法用于确定以前是否是Java 8的版本。

// log4j-core:2.10.0
private static boolean isPreJava8() {
    String version = System.getProperty("java.version");
    String[] parts = version.split("\\.");
    try {
        int major = Integer.parseInt(parts[1]);
        return major < 8;
    } catch (Exception var3) {
        return true;
    }
}

如果您使用Java 11运行此方法,则将获得真实,这意味着11是8之前的版本。这显然是错误的。您可以说出一个简单的调试是什么问题。

当然,我使用的版本是log4j核:2.10.0。我相信著名的Log4J项目必须在以后的版本中解决此问题。

果然,这个问题是在提交上特别解决的。

维修方法也很低,这意味着要判断第一点是1,然后以新的方式做出判断,即使用该点背后的数字作为主要版本。

好吧,似乎将该项目从8升级到11的最安全方法是同时升级Log4J三方依赖的旧版本。

什么是原则

让我们探讨下面的该项目的原则。 Github的官方网站上给出了建筑图。

左侧是运行项目的代理分析,上面是对静态jar和类文件等的分析。当简短解析符号时,它们是不同的。

中间部分是符号解析完成后,需要读取规则规则。这些规则是确定是否存在兼容性问题的逻辑。如果他们匹配,将记录他们。

右下角是输出刚刚以更友好的方式记录的兼容性问题,例如HTML。

因此,整个架构仍然非常清楚,重点是如何处理细节,我只会在这里谈论关键链接。

代理方法分析可能不是很直观。如果您想了解,则可以从此标准Javaagent项目的首要方法开始。

在这里,我碰巧了解了另一种直接扫描类文件或JAR文件进行静态扫描的方法,这非常直观。

首先,我们故意编写了可以触发java的代码。上面提到的Version格式兼容性问题。

class Hello {
    public static void main(String[] var0) {
        System.out.println("hello");
        System.out.println(System.getProperty("java.version"));
    }
}

然后将其编译到类文件中,并将其作为扫描文件夹放入ClassFiles文件夹中。

然后执行SH命令,表明您检查文件夹中的风险项目是否迁移至11。

sh analysis.sh -f 8 -t 11 -o report.html classFiles

该SH脚本实际上是执行分析并将上述参数传递到ARG中的主要方法。

// org/eclipse/emt4j/analysis/AnalysisMain.java
public class AnalysisMain { 
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException, URISyntaxException {
        ...
        ReportConfig config = doAnalysis(args, ...);
        doReport(config, ...);
    }
    ...
}

因此,从这个入口开始是一件好事。

主方法的结构也很简单。 DoAnalysis分析了这些类文件并绘制结果。 Doreport将可视化分析结果,例如生成HTML文件。

我不会一一扩展特定的呼叫链,我只会查看非常关键的链接。首先,ClassAnalyzer中的ProcessClass方法使用ASM将类文件解析为各种符号,并将其保存在ClassSymbol对象中。

// org/eclipse/emt4j/analysis/analyzer/ClassAnalyzer.java
protected static void processClass(byte[] classFileContent ...) {
    ClassSymbol symbol = ClassInspectorInstance.getInstance().getSymbolInClass(classFileContent);
    ...
}

然后,各种规则文件使用这些符号信息来做出判断,例如holeclassrule,这意味着需要整个类文件信息来做出判断。

@RuleImpl(type = "whole-class")
public class WholeClassRule extends ExecutableRule {
    ...
    @Override
    protected CheckResult check(Dependency dependency) {
        Map mvelMap = new HashMap<>();
        mvelMap.put("typeSet", dependency.getClassSymbol().getTypeSet());
        mvelMap.put("methodSet", toMethodIdentifierSet(dependency.getClassSymbol().getCallMethodSet()));
        mvelMap.put("cpSet", dependency.getClassSymbol().getConstantPoolSet());
        Object result = MVEL.eval(mvel2Rule, mvelMap);
        if (result instanceof Boolean) {
            return ((Boolean) result) ? CheckResult.FAIL : CheckResult.PASS;
        } else {
            throw new JdkMigrationException("Mvel2 rule file" + mvel2RuleFile + " must return a boolean result!Now result type is : " + result.getClass());
        }
    }
}

在这里,我们刚刚删除符号信息,并将其放入MvelMap中,即排版类型集合,MethodSet方法集合和CPSET CONST CONST池集合。

接下来,使用第三方班级库Mvel进行判断。这是一个工具类,可以使用表达式来做出匹配的判断。这很方便。规则表达式写在此mvel2rule中。

有许多mvel2rule,其中要检查Java的兼容性问题的表达式写在以下文件中。

// emt4j-common/src/main/resources/default/rule/8to11/data/mvel2-rule-getjavaversion.cfg
methodSet.contains('java.lang.System.getProperty') && 
(
  cpSet.contains('java.version') || 
  cpSet.contains('java.specification.version') || 
  cpSet.contains('java.runtime.version')
)

此规则表达式很容易理解,您可以理解它而不理解其写作方法,只需使用它

system.getProperty

方法,有一个

java.version或java.specification.version或java.runtime.version

当它被认为是兼容性问题时。

可以看出,这个判断非常粗糙,只是一个简单的字符串包含判断。可以看出,兼容性问题的判断无法逃脱此方法。不要认为使用任何智能分析方法。

当记录此兼容性问题并最终输出HTML文件时,将通过ResourceBundle查看官方文档说明,详细信息将写入HTML文件中。

最后,我看到了效果,这很简单。

再说几句话

通过体验和理解这个项目,我们可以学到很多东西。尽管麻雀很小,但它具有所有内部器官。

首先,它是通过代理和SH提供给用户的,但是中间的分析和判断逻辑是共享的。

然后,该项目使用专门解析类文件的ASM工具,提取符号信息以供以后使用。

MVEL也被用作规则判断的工具,因此规则判断只需要书写表达方式。

当最终输出为HTML时,为了查询相应兼容性问题的官方描述,ResourceBundle用于查找官方文档描述。因此,我们可以继续更深入地了解官方文档的查询规格,这是从代码级别进行的,并且非常严格。

一个好的工具是使用如此多的知名工具使自己方便。然后,我们还可以使用这个项目来做自己的事情。

例如,您制作的工具甚至是您自定义的JDK需要检查业务代码中是否存在兼容性问题,或者您只想扫描业务代码中是否有任何关心的内容,那么您就可以修改各种该项目中的规则表达式并自定义您自己的HTML报告格式以完善此功能。

其他事情,如何扫描班级,如何解析班级符号,如何将规则判决来判断以及如何输出和渲染HTML,您不必自己做。

1。

2。

3。

4。

5。

你可能想看:
« 上一篇
下一篇 »

相关推荐

java中什么是冒泡,冒泡算法

2026年09月06日

27阅读

java中冒号,java双冒号

2026年09月06日

26阅读

java中的->,java中的是什么意思

2026年09月06日

24阅读

java中的super用法,Java中super的说明

2026年09月06日

28阅读

java中反射的应用,java中反射的应用场景

2026年09月06日

25阅读

java中开关的定义,Java关键字有哪些

2026年09月06日

26阅读