1 - sdkman

sdkman

1.1 - sdkman介绍

软件开发工具包管理器

介绍

https://sdkman.io/

认识SDKMAN!- 您的可靠伙伴,轻松管理Unix系统上的多个软件开发工具包。想象一下,有不同版本的SDK,需要一种无压力的方式在它们之间切换。SDKMAN!借助其易于使用的命令行界面(CLI)和API,以前称为GVM,Groovy enVirgin Manager,SDKMAN!从apt、pip、RVM和rbenv甚至Git等熟悉的工具中汲取灵感。可以将它看作是您的有用工具包朋友,随时准备为您简化SDK管理。

  • By Developers, for Developers:简化生活。不再需要搜索下载, 档案,或修补 HOME和PATH环境变量。
  • Java一站式:为JVM安装软件开发工具包,如Java,Scala, Kotlin和Groovy。Ant、Gradle、Grails、Maven、SBT、Spark、Spring boot、Vert.x和许多其他版本也支持。
  • 轻量级: 用Rust和bash编写,只需要curl, zip和 解压缩依赖项以呈现在系统上。 甚至可以和 zsh 一起工作。
  • 多平台: 可在各种基于UNIX的平台上无缝运行, 包括macOS、Linux和 Windows 上的 Windows Linux 子系统(WSL) 。
  • API: 新客户端可以很容易地通过使用我们的 open Broker API 编写。供应商可以通过安全的 Vendor API发布和宣布他们自己的版本。
  • 开源: 由全球开发者社区提供支持。

1.2 - sdkman安装

安装sdkman

参考官方文档: https://sdkman.io/install

安装

在UNIX上安装SDKMAN是轻而易举的事。它可以轻松地在macOS、Linux和Windows(使用WSL)上设置。此外,它还兼容Bash和 zsh。

安装方式:

curl -s "https://get.sdkman.io" | bash

Linux安装

这是在 linux mint 22下安装的输出日志:

......
                                                                 Now attempting installation...


Looking for a previous installation of SDKMAN...
Looking for unzip...
Looking for zip...
Looking for tar...
Looking for curl...
Looking for sed...
Installing SDKMAN scripts...
Create distribution directories...
Getting available candidates...
Prime platform file...
Prime the config file...
Installing script cli archive...
* Downloading...
######################################################################## 100.0%
* Checking archive integrity...
* Extracting archive...
* Copying archive contents...
* Cleaning up...

Installing script cli archive...
* Downloading...
######################################################################## 100.0%
* Checking archive integrity...
* Extracting archive...
* Copying archive contents...
* Cleaning up...

Set version to 5.18.2 ...
Set native version to 0.4.6 ...
Attempt update of interactive bash profile on regular UNIX...
Added sdkman init snippet to /home/sky/.bashrc
Attempt update of zsh profile...
Updated existing /home/sky/.zshrc



All done!

打开一个新的终端或在同一个shell中运行以下命令:

source "$HOME/.sdkman/bin/sdkman-init.sh"

验证一下:

sdk version

输出为:

SDKMAN!
script: 5.18.2
native: 0.4.6

windows 安装

WSL

在尝试安装SDKMAN之前,先安装Windows Subsystem for Linux(WSL)。一个基本的工具集(bash,zip,unzip,curl)是必要的。大多数时候,它是开箱即用的。

备注:我现在不太喜欢使用 wsl,先不用。

Git Bash

备注:稍后尝试。

1.3 - sdkman的使用

介绍如何使用 sdkman

参考官方文档: https://sdkman.io/usage

1.3.1 - 列出候选

通过 list 命令列出可供选择的候选者列表

通过 sdk list 命令可以列出当前平台上可供选择的候选者列表:

sdk list

命令输出为:

================================================================================
Available Candidates
================================================================================
q-quit                                  /-search down
j-down                                  ?-search up
k-up                                    h-help

--------------------------------------------------------------------------------
Apache ActiveMQ (Classic) (5.17.1)                  https://activemq.apache.org/

Apache ActiveMQ® is a popular open source, multi-protocol, Java-based message
broker. It supports industry standard protocols so users get the benefits of
client choices across a broad range of languages and platforms. Connect from
clients written in JavaScript, C, C++, Python, .Net, and more. Integrate your
multi-platform applications using the ubiquitous AMQP protocol. Exchange
messages between your web applications using STOMP over websockets. Manage your
IoT devices using MQTT. Support your existing JMS infrastructure and beyond.
ActiveMQ offers the power and flexibility to support any messaging use-case.

                                                          $ sdk install activemq
--------------------------------------------------------------------------------
Ant (1.10.14)                                            https://ant.apache.org/

Apache Ant is a Java library and command-line tool whose mission is to drive
processes described in build files as targets and extension points dependent
upon each other. The main known usage of Ant is the build of Java applications.
Ant supplies a number of built-in tasks allowing to compile, assemble, test and
run Java applications. Ant can also be used effectively to build non Java
applications, for instance C or C++ applications. More generally, Ant can be
used to pilot any type of process which can be described in terms of targets and
tasks.

                                                               $ sdk install ant
......

会列出每一个支持的软件的名字/介绍和默认版本。

完整输出列表可以见 list.txt

支持列表

看看 sdkman 具体支持哪些东东。

Apache ActiveMQ

Apache ActiveMQ® is a popular open source, multi-protocol, Java-based message broker. It supports industry standard protocols so users get the benefits of client choices across a broad range of languages and platforms. Connect from clients written in JavaScript, C, C++, Python, .Net, and more. Integrate your multi-platform applications using the ubiquitous AMQP protocol. Exchange messages between your web applications using STOMP over websockets. Manage your IoT devices using MQTT. Support your existing JMS infrastructure and beyond.

ActiveMQ offers the power and flexibility to support any messaging use-case.

Apache ActiveMQ® 是一种流行的开源、多协议、基于 Java 的消息代理。它支持行业标准协议,因此用户可以从多种语言和平台的客户端选择中获益。可从 JavaScript、C、C++、Python、.Net 等语言编写的客户端进行连接。使用无处不在的 AMQP 协议集成您的多平台应用程序。通过 webockets 使用 STOMP 在网络应用程序之间交换信息。使用 MQTT 管理物联网设备。支持现有的JMS基础架构及更多。

ActiveMQ具有强大的功能和灵活性,可以支持任何消息传递使用情况。

Ant

Apache Ant is a Java library and command-line tool whose mission is to drive processes described in build files as targets and extension points dependent upon each other. The main known usage of Ant is the build of Java applications.

Ant supplies a number of built-in tasks allowing to compile, assemble, test and run Java applications. Ant can also be used effectively to build non Java applications, for instance C or C++ applications. More generally, Ant can be used to pilot any type of process which can be described in terms of targets and tasks.

Apache Ant 是一个 Java 库和命令行工具,其任务是将构建文件中描述的进程作为相互依赖的目标和扩展点来驱动。Ant 的主要用途是构建 Java 应用程序。

Ant 提供了大量内置任务,允许编译、组装、测试和运行 Java 应用程序。Ant 还能有效地用于构建非 Java 应用程序,例如 C 或 C++ 应用程序。更广泛地说,Ant 可用于引导任何类型的进程,这些进程可以用目标和任务来描述。

AsciidoctorJ

AsciidoctorJ is the official library for running Asciidoctor on the JVM. Using AsciidoctorJ, you can convert AsciiDoc content or analyze the structure of a parsed AsciiDoc document from Java and other JVM languages.

AsciidoctorJ 是在 JVM 上运行 Asciidoctor 的官方库。使用 AsciidoctorJ,你可以转换 AsciiDoc 内容或分析 Java 和其他 JVM 语言解析的 AsciiDoc 文档结构。

Ballerina

Open source programming language and platform for cloud-era application programmers to easily write software that just works.

开源代码编程语言和平台,让云时代的应用程序员轻松编写能正常运行的软件。

Bld

bld is a build system that allows you to write your build logic in pure Java.

bld was created because we’re not really interested in build tools. We use them because we have to, but we’d rather just get on with coding the real stuff.

bld 是一个构建系统,允许您用纯 Java 编写构建逻辑。

之所以创建 bld,是因为我们对构建工具并不感兴趣。我们不得不使用它们,但我们更愿意继续编写真正的代码。

Bpipe

Bpipe is a framework for running computational pipelines and workflows

Bpipe是一个运行计算管道和工作流的框架

BTrace

BTrace is a safe, dynamic tracing tool for the Java platform. BTrace can be used to dynamically trace a running Java program (similar to DTrace for OpenSolaris applications and OS). BTrace dynamically instruments the classes of the target application to inject bytecode tracing code.

BTrace 是一款适用于 Java 平台的安全动态跟踪工具。BTrace 可用于动态跟踪运行中的 Java 程序(类似于 OpenSolaris 应用程序和操作系统的 DTrace)。BTrace 对目标应用程序的类进行动态检测,以注入字节码跟踪代码。

Concurnas

Concurnas is an open source JVM programming language designed for building reliable, scalable, high performance concurrent, distributed and parallel systems.

Concurnas 是一种开源 JVM 编程语言,设计用于构建可靠、可扩展、高性能的并发、分布式和并行系统。

ConnOR

ConnOR, short for ConnectOffsetReset, is a commandline tool for resetting Kafka Connect source connector offsets.

ConnOR 是 ConnectOffsetReset 的缩写,是重置 Kafka Connect 源连接器偏移量的命令行工具。

Coursier

Coursier is the Scala application and artifact manager. It can install Scala applications and setup your Scala development environment. It can also download and cache artifacts from the web.

Coursier 是 Scala 应用程序和工件管理器。它可以安装 Scala 应用程序并设置 Scala 开发环境。它还能从网上下载和缓存工件。

CUBA CLI

CUBA CLI is an open source command line utility that enables you to easily create projects based on CUBA Platform

CUBA CLI 是一款开源命令行工具,可让您轻松创建基于 CUBA Platform 的项目。

CXF

Apache CXF is an open source services framework. CXF helps you build and develop services using frontend programming APIs, like JAX-WS and JAX-RS. These services can speak a variety of protocols such as SOAP, XML/HTTP, RESTful HTTP, or CORBA and work over a variety of transports such as HTTP, JMS or JBI.

Apache CXF 是一个开源服务框架。CXF 可帮助您使用 JAX-WS 和 JAX-RS 等前端编程 API 构建和开发服务。这些服务可以使用 SOAP、XML/HTTP、RESTful HTTP 或 CORBA 等多种协议,并通过 HTTP、JMS 或 JBI 等多种传输方式工作。

Detekt

A static code analysis tool for the Kotlin programming language

用于 Kotlin 编程语言的静态代码分析工具

docToolchain

docToolchain is an implementation of the docs-as-code approach for software architecture plus some additional automation. The basis of docToolchain is the philosophy that software documentation should be treated in the same way as code together with the arc42 template for software architecture.

docToolchain 是对软件架构 “文档即代码”(docs-as-code)方法的实现,并增加了一些自动化功能。docToolchain 的基础是软件文档应与代码一样处理的理念以及软件架构的 arc42 模板。

Apache Flink is an open-source, unified stream-processing and batch-processing framework.It’s a distributed processing engine for stateful computations over unbounded and bounded data streams.It has been designed to run in all common cluster environments, perform computations at in-memory speed and at any scale.

Apache Flink 是一个开源、统一的流处理和批处理框架。它是一个分布式处理引擎,用于在无界和有界数据流上进行有状态计算。它设计用于在所有常见的集群环境中运行,以内存中的速度和任何规模执行计算。

Gaiden

Gaiden is a tool that makes it easy to create documentation with Markdown.

Gaiden是一个工具,可以轻松地使用Markdown创建文档。

Graal Cloud Native

Graal Cloud Native (GCN) is a curated set of Micronaut(tm) framework modules designed from the ground up to be compiled ahead-of-time with GraalVM Native image resulting in native executables ideal for microservices.With GCN, You can build portable cloud-native Java microservices that start instantly and use fewer resources to reduce compute costs.

Graal Cloud Native (GCN) 是一套经过精心设计的 Micronaut(tm) 框架模块,其设计初衷是通过 GraalVM Native 镜像进行提前编译,从而生成适用于微服务的本机可执行文件。

Grace Framework

Grace is a powerful open-source, One-Person web application Framework to help developers build Spring Boot applications rapidly using the Groovy programming language. Grace is a fork of Grails 5 that started development in early 2022.

Grace 是一个功能强大的开源单人 Web 应用程序框架,可帮助开发人员使用 Groovy 编程语言快速构建 Spring Boot 应用程序。Grace 是 Grails 5 的一个分叉,于 2022 年初开始开发。

Gradle

Gradle is a build automation tool that builds upon the concepts of Apache Ant and Apache Maven and introduces a Groovy-based domain-specific language (DSL) instead of the more traditional XML form of declaring the project configuration.

Gradle uses a directed acyclic graph (DAG) to determine the order in which tasks can be run.

Gradle 是一款构建自动化工具,它以 Apache Ant 和 Apache Maven 的概念为基础,引入了基于 Groovy 的特定领域语言(DSL),而不是更传统的 XML 形式来声明项目配置。

Gradle 使用有向无环图(DAG)来决定任务的运行顺序。

Gradle profiler

A tool for gathering profiling and benchmarking information for Gradle builds

用于收集Gradle构建的分析和基准测试信息的工具

Grails

Grails is a powerful web framework, for the Java platform aimed at multiplying developers productivity thanks to a Convention-over-Configuration, sensible defaults and opinionated APIs. It integrates smoothly with the JVM, allowing you to be immediately productive whilst providing powerful features, including integrated ORM, Domain-Specific Languages, runtime and compile-time meta-programming and Asynchronous programming.

Grails 是一个功能强大的 Web 框架,适用于 Java 平台,旨在通过 “配置公约”、合理的默认设置和有主见的 API 来提高开发人员的工作效率。它能与 JVM 平滑集成,让您立即提高工作效率,同时提供强大的功能,包括集成的 ORM、特定域语言、运行时和编译时元编程以及异步编程。

Groovy

Groovy is a powerful, optionally typed and dynamic language, with static-typing and static compilation capabilities, for the Java platform aimed at multiplying developers’ productivity thanks to a concise, familiar and easy to learn syntax.

It integrates smoothly with any Java program, and immediately delivers to your application powerful features, including scripting capabilities, Domain-Specific Language authoring, runtime and compile-time meta-programming and functional programming.

Groovy 是一种功能强大、可选择类型的动态语言,具有静态类型和静态编译功能,适用于 Java 平台,旨在通过简洁、熟悉和易学的语法提高开发人员的工作效率。

它能与任何 Java 程序顺利集成,并能立即为您的应用程序提供强大的功能,包括脚本功能、特定域语言编写、运行时和编译时元编程以及函数式编程。

GroovyServ

GroovyServ reduces startup time of the JVM for runnning Groovy significantly. It depends on your environments, but in most cases, it’s 10 to 20 times faster than regular Groovy.

GroovyServ 可大大缩短运行 Groovy 的 JVM 的启动时间。这取决于您的环境,但在大多数情况下,它比普通的 Groovy 快 10 到 20 倍。

hadoop

Apache™ Hadoop® project develops open-source software for reliable, scalable, distributed computing.It’s a framework that allows for the distributed processing of large data sets across clusters of computersusing simple programming models.It is designed to scale up from single servers to thousands of machines, each offering local computation and storage.

Apache™ Hadoop® 项目为可靠、可扩展的分布式计算开发开源软件。它是一个框架,允许使用简单的编程模型在计算机集群间分布式处理大型数据集。

Helidon CLI

The Helidon CLI lets you easily create a Helidon project by picking from a set of archetypes. It also supports a developer loop that performs continuous compilation and application restart, so you can easily iterate over source code changes.

Helidon CLI 可让您从一系列原型中轻松创建 Helidon 项目。它还支持一个开发人员循环,可执行连续编译和应用程序重启,因此你可以轻松迭代源代码变更。

http4k

http4k is the Functional toolkit for building HTTP applications in Kotlin

http4k是用于在 Kotlin 中构建HTTP应用程序的功能工具包

Infrastructor

Infrastructor is an open source server provisioning tool written in Groovy

Infrastructor是一个用Groovy编写的开源服务器配置工具

Jarviz

Jarviz is a JAR analyzer tool. You can obtaine metadata from a JAR such as its manifest, manifest entries, bytecode versions, declarative services, and more.

Jarviz 是一款 JAR 分析工具。你可以从 JAR 中获取元数据,如清单、清单条目、字节码版本、声明式服务等。

Java

Java Platform, Standard Edition (or Java SE) is a widely used platform for development and deployment of portable code for desktop and server environments.

Java SE uses the object-oriented Java programming language. It is part of the Java software-platform family. Java SE defines a wide range of general-purpose APIs – such as Java APIs for the Java Class Library – and also includes the Java Language Specification and the Java Virtual Machine Specification.

Java 平台标准版(或 Java SE)是一个广泛使用的平台,用于开发和部署桌面和服务器环境的可移植代码。

Java SE 使用面向对象的 Java 编程语言。它是 Java 软件平台系列的一部分。Java SE 定义了大量通用 API(如 Java 类库的 Java API),还包括 Java 语言规范和 Java 虚拟机规范。

JBake

JBake is a Java based, open source, static site/blog generator for developers and designers.

JBake 是一款基于 Java 的开源静态网站/博客生成器,适用于开发人员和设计人员。

JBang

JBang makes it easy to use Java for scripting. It lets you use a single file for code and dependency management and allows you to run it directly.

JBang 可让您轻松使用 Java 编写脚本。它让您使用单一文件进行代码和依赖性管理,并允许您直接运行它。

2 - JavaUpgrades

JavaUpgrades

2.1 - JavaUpgrades介绍

JavaUpgrades介绍

概述

https://github.com/johanjanssen/JavaUpgrades

2.2 - JavaUpgrades文档说明

JavaUpgrades介绍

项目首页介绍

https://github.com/johanjanssen/JavaUpgrades

Java 升级错误和解决方案示例

该项目展示了 Java 升级过程中遇到的错误以及必要的修复方法。

每个 Java 版本都有一个 Maven 模块,显示从该版本开始出错的地方以及如何修复。

本项目使用 Maven,但其他构建工具也会出现同样的问题。

本自述首先介绍了 Java 的一般问题和解决方案,然后介绍了每个特定 Java 版本的问题和解决方案。然后介绍在一台机器上运行多个 JDK 的各种方法。

最后一部分还介绍了如何运行示例。例如,Java 15 示例可以在 Java 14 上运行。在 Java 15 上运行时,损坏的示例会失败,而固定的示例会成功。

自动升级 Java

OpenRewrite 提供了各种自动升级应用程序甚至改进代码的方法。它会在本地进行修改,然后你可以决定是否要提交所有修改,或者是否要进行修改。与手动升级相比,使用 OpenRewrite 可以节省大量时间。

他们提供的一些秘诀:

Java 面临的普遍挑战

本文档描述了 Java 的较大变化。Java 还删除了许多(较小的)项目。本章列出了被移除的各种类别。有关详细信息,请查看发行说明:

Java 发行说明:

Security 路线图:

OpenJDK 特性:

删除虚拟机标志/选项

例如

-XX:+AggressiveOpts

-Xoptimize

删除(根)证书

“The T-Systems Deutsche Telekom Root CA 2 certificate has expired and was removed from the cacerts keystore”

“T-Systems Deutsche Telekom Root CA 2 证书已过期,已从 cacerts 密钥库中删除”

删除加密算法

被认为不安全的算法已被删除。

删除垃圾回收器

例如,在 14 中删除了并发标记和清扫(CMS)垃圾收集器。

从 API 中移除

API 的部分内容(如方法)可能会被弃用,之后又会被移除。

您可以按 Java 版本查看 API 中已废弃和移除的部分。例如,通过 Java 版本年鉴 或 foojay

已删除的工具

有些工具已不再可用,有些工具(如 JDK Mission Control 和 JavaFX)现在可从不同供应商处以单独构建版的形式获得。

有些 JDK(如 ojdkbuild 和 Liberica JDK 的某些构建版)仍提供包含某些工具的 JDK。

各 Java 版本的问题和解决方案

Java 11

JEP 320: 删除 Java EE 和 CORBA 模块

Java 11 中移除了 EE 包。如果您仍然需要它们,可以将它们添加为 Maven/Gradle 依赖项。

请注意,您应使用新的 jakarta 软件包,因为旧软件包已不再更新。

例如,JAXB 可以通过下面列出的依赖关系添加。不过,它已不再更新,最新版本是 2.3.0。

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.0</version>
</dependency>

相反,您应该使用 Jakarta 依赖项,它有更新的 3.0.0 版本:

<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>3.0.0</version>
</dependency>

移除 javax.activation

错误示例

可在 java11/javaee_removed_broken 下找到示例代码

package javax.activation does not exist
cannot find symbol
[ERROR]   symbol:   class URLDataSource

解决方案

可在 java11/javaee_removed_fixed_new_package 下找到示例代码

添加必要的依赖项:

<dependency>
    <groupId>com.sun.activation</groupId>
    <artifactId>jakarta.activation</artifactId>
    <version>2.0.1</version>
</dependency>

移除 javax.annotation

错误示例 示例代码可在 java11/javaee_removed_broken 下找到。

package javax.annotation does not exist
cannot find symbol
[ERROR]   symbol:   class PostConstruct

解决方案 可在 java11/javaee_removed_fixed_new_package 下找到示例代码

添加必要的依赖项:

<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>2.0.0</version>
</dependency>

移除 javax.transaction

错误示例

可在 java11/javaee_removed_broken 下找到示例代码

package javax.transaction does not exist
cannot find symbol
[ERROR]   symbol:   class TransactionRequiredException

解决方案 可在 java11/javaee_removed_fixed_new_package 下找到示例代码

添加必要的依赖项:

<dependency>
    <groupId>jakarta.transaction</groupId>
    <artifactId>jakarta.transaction-api</artifactId>
    <version>2.0.0</version>
</dependency>

移除 javax.xml.bind

示例错误

示例代码可以在 java11/javaee_removed_broken 下找到

package javax.xml.bind.annotation does not exist
cannot find symbol
[ERROR]   symbol: class XmlRootElement
cannot find symbol
[ERROR]   symbol:   class JAXBException

解决方案

示例代码可以在 java11/javaee_removed_fixed_new_package 下找到

添加必要的依赖项:

对于 API,有:

<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>3.0.0</version>
</dependency>

对于实现,下面列出了几个选项。如果您已经使用其中一个作为传递依赖项,那么最好使用该依赖项来避免冲突。

以下命令可用于检查是否已通过传递依赖项使用其中一个实现:

mvn dependency:tree -Dincludes=org.glassfish.jaxb:jaxb-runtime
mvn dependency:tree -Dincludes=com.sun.xml.bind:jaxb-impl

如果您没有 JAXB 实现作为传递依赖项,那么最好使用以下 Glassfish 实现。

<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>3.0.0</version>
    <scope>runtime</scope>
</dependency>

或者 jaxb-impl,它现在称为旧 JAXB 运行时

<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>3.0.0</version>
</dependency>

删除 javax.jws javax.xml.soap javax.xml.ws

示例错误

示例代码可以在 java11/javaee_removed_broken 下找到

package javax.xml.ws does not exist
cannot find symbol
[ERROR]   symbol:   class Service

解决方案

示例代码可以在 java11/javaee_removed_fixed_new_package 下找到

添加必要的依赖项:

<dependency>
    <groupId>jakarta.xml.ws</groupId>
    <artifactId>jakarta.xml.ws-api</artifactId>
    <version>3.0.0</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-rt</artifactId>
    <version>3.0.0</version>
</dependency>

删除 Corba javax.activity javax.rmi.*

没有发布 Corba 的官方替换/依赖项

解决方案:

从 Corba 迁移或使用类似 glassfish-corba 的东西

字体删除

JDK 包含一些字体,但在 Java 11 中删除了它们。如果应用程序使用了这些字体,而操作系统未提供这些字体,则会发生错误。

来自 AzulAdoptOpenJDK 的详细信息

示例错误

示例代码可以在 java11/removed_fonts 下找到

java.lang.UnsatisfiedLinkError: /usr/local/openjdk-11/lib/libfontmanager.so: 
  libfreetype.so.6: cannot open shared object file: No such file or director
java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11FontManager

解决方案

示例代码可在 DockerfileWithFonts 中找到

安装必要的字体,例如:

apt install fontconfig

根据你的方案,你可能需要添加一些额外的包,例如:libfreetype6 fontconfig fonts-dejavu。

一些 JDK 会自动安装所需的软件包。

JavaFX 删除

JavaFX 已从 JDK 中删除,并继续作为 OpenJFX。

一些供应商提供 OpenJFX 的构建,例如 Gluon

一些供应商提供包含 OpenJFX 的 JDK 版本,例如 Liberica 的完整版ojdkbuild

使用 OpenJFX 的 (Maven) 依赖项

Java Mission Control (JMC) 已删除

使用 JDK Mission control 的内部版本之一:

Java 15

JEP 372:删除 Nashorn JavaScript 引擎

Nashorn 不再包含在标准 JDK 中。

示例错误

示例代码可以在 java15/nashorn_broken 下找到

java.lang.NullPointerException: Cannot invoke "javax.script.ScriptEngine.eval(String)" because "engine" is null

解决方案

示例代码可以在 java15/nashorn_fixed 下找到

添加必要的依赖项:

<dependency>
    <groupId>org.openjdk.nashorn</groupId>
    <artifactId>nashorn-core</artifactId>
    <version>15.4</version>
</dependency>

Java 16

JEP 396:默认情况下高度封装 JDK 内部结构

默认情况下,JDK 的内部结构不能再使用。这主要影响使用 JDK 低级功能的工具。

示例错误

示例代码可以在 java16/lombok_broken 下找到

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project broken: Fatal error compiling: java.lang.IllegalAccessError: class lombok.javac.apt.LombokProcessor (in unnamed module @0x21bd20ee) cannot access class com.sun.tools.javac.processing.JavacProcessingEnvironment (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.processing to unnamed module @0x21bd20ee -> [Help 1]

解决方案

示例代码可以在 java16/lombok_fixed 下找到

最好使用导致问题的依赖项的新版本。例如,Lombok 1.18.20 包括对 Java 16 的支持:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.20</version>
    <scope>provided</scope>
</dependency>

如果没有新的依赖项可用,则可以打开 JDK 内部,以便可以使用它们。但是,这并不是最漂亮的解决方案:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
        <fork>true</fork>
        <compilerArgs>
            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED</arg>
            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</arg>
            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED</arg>
        </compilerArgs>
    </configuration>
</plugin>

Java 17

Gradle

  • 更新到 Gradle 7.3 以获得 Java 17 支持
  • 更新到 Kotlin 1.6.0 以便能够将 jvmTarget 设置为 17

JEP 403:高度封装 JDK 内部

启动器选项 –illegal-access 不再适用于访问内部 JDK API。

示例错误

java.lang.reflect.InaccessibleObjectException: Unable to make  accessible: module java.base does not "opens …" to unnamed module 

解决方案

  • 如果由依赖项触发,请升级依赖项
  • 重构代码以不再使用内部 JDK API
  • 作为最后的手段,例如:--add-opens
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <argLine>
            --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED
        </argLine>
    </configuration>
</plugin>

JEP?

Mockito 在模拟使用值中方法的枚举时会引发异常,例如:

public enum ExampleEnum {
    TEST {
        public String retrieve() {
            return "test";
        }
    };
}
@ExtendWith(MockitoExtension.class)
public class ExampleEnumTest {

    @Mock
    private ExampleEnum exampleEnum;

    @Test
    public void testEnumWithMethods() {
        assertNotNull(exampleEnum);
    }
}

示例错误

示例代码可以在 java17/mockito_fixed 下找到

org.mockito.exceptions.base.MockitoException:

Mockito cannot mock this class: class com.example.ExampleEnum.

If you're not sure why you're getting this error, please report to the mailing list.


Java               : 17
JVM vendor name    : Oracle Corporation
JVM vendor version : 17-ea+24-2164
JVM name           : OpenJDK 64-Bit Server VM
JVM version        : 17-ea+24-2164
JVM info           : mixed mode, sharing
OS name            : Linux
OS version         : 4.19.76-linuxkit


You are seeing this disclaimer because Mockito is configured to create inlined mocks.
You can learn about inline mocks and their limitations under item #39 of the Mockito class javadoc.

Underlying exception : org.mockito.exceptions.base.MockitoException: Could not modify all classes [class com.example.ExampleEnum, interface java.lang.constant.Constable, class java.lang.Object, interface java.lang.Comparable, interface java.io.Serializable, class java.lang.Enum]
Caused by: org.mockito.exceptions.base.MockitoException: Could not modify all classes [class com.example.ExampleEnum, interface java.lang.constant.Constable, class java.lang.Object, interface java.lang.Comparable, interface java.io.Serializable, class java.lang.Enum]
Caused by: java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the class NestHost, NestMembers, Record, or PermittedSubclasses attribute

解决方案

尚不可用,请参阅 Mockito GitHub 存储库中的问题,其中提到了解决方法。

Java 21

Bytebuddy

示例错误

通过 Bytebuddy 的 EqualsVerifier

-> Java 21 (65) is not supported by the current version of Byte Buddy which officially supports Java 20 (64) - update Byte Buddy or set net.bytebuddy.experimental as a VM property

解决方案

升级到支持 Java 21 的 Bytebuddy 版本或使用解决方法:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <argLine>-Dnet.bytebuddy.experimental=true</argLine><!-- Needed as EqualsVerifier uses Byte Buddy which doesn't support Java 21 -->
    </configuration>
</plugin>

所有 Java 版本

Unsupported class file major version 61 in JaCoCo

An error has occurred in JaCoCo Aggregate report generation. Error while creating report: Error while analyzing … Unsupported class file major version X
Execution default of goal org.pitest:pitest-maven:1.4.10:mutationCoverage failed: Unsupported class file major version 61 
Execution repackage of goal org.springframework.boot:spring-boot-maven-plugin:2.2.10.RELEASE:repackage failed: Unsupported class file major version 61

解决方案

类文件主要版本 61 用于 Java 17。确保您的插件/依赖项是最新的并支持 Java 17。

  • 更新插件/依赖项

在一台计算机上运行多个 JDK

在运行示例之前设置JAVA_HOME

Maven 使用 JAVA_HOME 的值来选择 JDK。

显示当前JAVA_HOME

echo $JAVA_HOME
C:\Program Files\AdoptOpenJDK\jdk-16.0.0.36-hotspot

设置为另一个 JDK:JAVA_HOME

JAVA_HOME="[location of JDK]"

然后在其中一个 Java 目录(java11、java16…)中使用以下 Maven 命令来构建所有子模块,并在出现问题时继续:

mvn compile --fail-at-end -Dmaven.compiler.release=[Specify JDK version. Don't use this on Java 8 as it's not supported]

或者简短的版本:

mvn compile -fae -Dmaven.compiler.release=[Specify JDK version. Don't use this on Java 8 as it's not supported]

Java 8 的脚本版本

mvn compile -fae -Dmaven.compiler.target=8 -Dmaven.compiler.source=8

或者在 Maven 版本中更改:pom.xml

<properties>
    <maven.compiler.release>7</maven.compiler.release>
</properties>

使用 Docker 容器

然后在其中一个 Java 目录(java11、java16…)中使用以下 Docker 命令:

将JDK_VERSION更改为所需的任何版本(11 或更高版本):

docker build -t javaupgrades -f ..\Dockerfile --build-arg DISABLE_CACHE="%date%-%time%" --build-arg JDK_VERSION=17 --progress=plain .

或者在 Java 8 上构建,这需要不同的配置:

docker build -t javaupgrades -f ..\DockerfileJava8 --build-arg DISABLE_CACHE="%date%-%time%" .

Maven 工具链

Maven 工具链可用于配置计算机上存在的 JDK,然后选择一个用于项目的 JDK。pom.xml

首先创建一个位于 ${user.home}/.m2/toolchains.xml

<?xml version="1.0" encoding="UTF8"?>
<toolchains>
    <toolchain>
        <type>jdk</type>
        <provides>
            <version>8</version>
        </provides>
        <configuration>
            <jdkHome>/path/to/jdk/8</jdkHome>
        </configuration>
    </toolchain>
    <toolchain>
        <type>jdk</type>
        <provides>
            <version>11</version>
        </provides>
        <configuration>
            <jdkHome>/path/to/jdk/11</jdkHome>
        </configuration>
    </toolchain>
    <toolchain>
        <type>jdk</type>
        <provides>
            <version>16</version>
        </provides>
        <configuration>
            <jdkHome>/path/to/jdk/16</jdkHome>
        </configuration>
    </toolchain>
    <toolchain>
        <type>jdk</type>
        <provides>
            <version>17</version>
        </provides>
        <configuration>
            <jdkHome>/path/to/jdk/16</jdkHome>
        </configuration>
    </toolchain>
</toolchains>

然后在 pom.xml 中配置要使用 toolchains.xml 中的哪个 JDK:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-toolchains-plugin</artifactId>
            <version>3.0.0</version>
            <configuration>
                <toolchains>
                    <jdk>
                        <version>${maven.compiler.release}</version>
                    </jdk>
                </toolchains>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>toolchain</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

确保更新 Maven Compiler Plugin。当使用旧版本时,结合工具链插件,错误并不详细:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project broken: Compilation failure -> [Help 1]

使用较新版本的 Maven 编译器插件时,错误消息提供了更详细的信息:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.10.1:compile (default-compile) on project lombok_broken: Compilation failure
[ERROR] java.lang.IllegalAccessError: class lombok.javac.apt.LombokProcessor (in unnamed module @...) cannot access class com.sun.tools.javac.processing.JavacProcessingEnvironme
nt (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.processing to unnamed module @...

有趣的其他事情

多发布 JAR

多版本 JAR 可以创建一个 JAR 文件,该文件支持多个 Java 版本以实现向后兼容性。

此示例使用在 Java 11 中引入的 recordsString.isBlank()。该示例有两个主要目录:

  • src/main/java: 用于 Java 17 以下的 Java 版本
  • src/main/java17: 17及更高版本使用的

此示例的 JAR 文件应基于 Java 17 构建,然后可以在各种 Java 版本上使用。

以下命令可用于在 Java 17 上构建示例,然后在 8、11 和 17 上运行它们:

mvn package
run-multi-release-application.cmd
# docker build -t multi-release-jar --build-arg DISABLE_CACHE="%date%-%time%" --progress=plain .

确保所有 Java 版本的代码都包含相同的公共 API,否则可能会遇到运行时问题。IntelliJ 对此进行了检查,Java 17 现在包含验证 JAR 文件的 jar --validate 选项。像 Maven 这样的构建工具不会自动验证它。

2.3 - OpenRewrite

使用OpenRewrite工具进行java升级

https://docs.openrewrite.org/

2.3.1 - 迁移到Java17

迁移到Java17

https://docs.openrewrite.org/running-recipes/popular-recipe-guides/migrate-to-java-17

在本教程中,我们将使用 OpenRewrite 从 Java 8 自动迁移到 Java 17。将旧代码库升级到 Java 17 可能是一项艰巨而耗时的任务。作为开发人员,您可以使用 OpenRewrite 快速解决升级过程中遇到的最常见问题。

本配方涵盖以下主题:

  • 使用任何 Java EE 规范的应用程序都将把这些依赖关系迁移到 Jakarta EE 8。此外,迁移到 Jakarta EE 8 还将为那些对 Jakarta EE API 有传递依赖关系的项目添加显式运行时依赖关系。目前,只支持基于 Maven 的构建文件。

  • Java 早期版本中任何已废弃的 API(具有明确定义的迁移路径)都将自动应用到应用程序的源代码中。本秘诀中包含的补救措施最初是通过一个名为 Jdeprscan 的构建插件识别出来的。

  • 当应用程序尝试使用未通过模块系统公开导出的 API 时,将记录非法反射访问警告。如果众所周知的第三方库提供了符合 Java 模块系统的版本,本教程将对其进行升级。

配置示例

在项目中加入 OpenRewrite 插件并依赖 rewrite-migrate-java,即可应用 Java 17 迁移配方:

<build>
  <plugins>
    <plugin>
      <groupId>org.openrewrite.maven</groupId>
      <artifactId>rewrite-maven-plugin</artifactId>
      <version>5.13.0</version>
      <configuration>
        <activeRecipes>
          <recipe>org.openrewrite.java.migrate.UpgradeToJava17</recipe>
        </activeRecipes>
      </configuration>
      <dependencies>
        <dependency>
          <groupId>org.openrewrite.recipe</groupId>
          <artifactId>rewrite-migrate-java</artifactId>
          <version>2.3.0</version>
        </dependency>
      </dependencies>
    </plugin>
  </plugins>
</build>

这时,你就可以运行 mvn rewrite:rungradlew rewriteRun 来执行迁移了。运行迁移后,您可以使用 git diff(或类似工具)检查迁移结果,手动修复无法自动迁移的内容,然后提交迁移结果。

迁移前后

有关此配方所做更改的完整列表,请参阅 Java 11 和 Java 17 的参考页面。如果您有本项目尚未涵盖的特定用例,请联系我们的团队!

2.3.2 - 在不修改构建的情况下在 Maven 项目上运行 Rewrite

在不修改构建的情况下在 Maven 项目上运行 Rewrite

https://docs.openrewrite.org/running-recipes/running-rewrite-on-a-maven-project-without-modifying-the-build

在本教程中,我们将应用 Rewrite recipe (配方)添加到使用 Maven 构建的源代码存储库中,而无需修改构建本身。根据配方是否具有配置参数,此说明略有不同。请注意,您需要先安装 Maven 以运行 shell 命令。

在没有配置参数的情况下运行配方

如果您尝试运行的配方没有任何必需的配置参数,则可以通过执行 shell 命令来运行配方。

我们 recipe 文档 包括针对任何没有配置参数的配方运行的特定 shell 命令。您可能会发现复制并运行提供的命令比手动创建它更容易。

如果配方来自core Rewrite库(如删除未使用的导入),然后您可以运行以下命令并将 org.openrewrite.java.RemoveUnusedImports 替换为要运行的配方的路径:

mvn -U org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.openrewrite.java.RemoveUnusedImports

如果配方来自不同的库(例如迁移到 Jakarta EE 9),然后您可以运行以下命令并将 org.openrewrite.recipe:rewrite-migrate-java:LATEST 替换为配方的工件,并将 org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta 替换为要运行的配方的路径:

mvn -U org.openrewrite.maven:rewrite-maven-plugin:run \
  -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-migrate-java:LATEST \
  -Drewrite.activeRecipes=org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta

使用配置参数运行配方

如果您尝试运行的配方具有配置参数,则需要:

  1. 在项目根目录中创建或更新 rewrite.yml 文件.在那里,您需要创建一个新配方,该配方包装要运行的配方并指定要使用的参数。

  2. 运行一个 shell 命令,该命令执行您在步骤 1 中定义的新配方。

例如,如果你想运行 ChangePackage 配方 若要将 org.old.package.name 更改为 org.new.package.name,需要创建一个如下所示的 rewrite.yml 文件:

---
type: specs.openrewrite.org/v1beta/recipe
name: com.yourorg.NameYouDefine
recipeList:
  - org.openrewrite.java.ChangePackage:
      oldPackageName: org.old.package.name
      newPackageName: org.new.package.name

然后,您可以通过执行以下 shell 命令来运行该配方:

mvn -U org.openrewrite.maven:rewrite-maven-plugin:run \
  -Drewrite.activeRecipes=com.yourorg.NameYouDefine

3 - OpenRewrite

OpenRewrite工具的使用

https://docs.openrewrite.org/

3.1 - Rewrite介绍

OpenRewrite支持大规模分布式源代码重构,用于框架迁移、漏洞补丁和API迁移。

https://docs.openrewrite.org/

大规模自动化源代码重构

OpenRewrite支持大规模分布式源代码重构,用于框架迁移、漏洞补丁和API迁移。虽然最初的重点是 Java 语言,但 OpenRewrite 一直在扩大语言和框架的覆盖范围.

语义代码搜索和转换

OpenRewrite 项目是一个语义代码搜索以及 Java 和其他源代码的转换生态系统。它由一个预打包的重构配方平台组成,用于常见的框架迁移和风格一致性任务。它还允许您定义自定义配方以实现广泛的源代码转换。

OpenRewrite 有什么作用?

OpenRewrite 的工作原理是对无损语义树(LST) 表示您的源代码,并将修改后的树打印回源代码。然后,您可以查看代码中的更改并提交。对 LST 的修改在游客和访客被聚合成配方(recepes). OpenRewrite 配方对遵循原始格式的源代码进行微创更改。

例如,如果要在所有测试文件中一致地使用静态导入,而不是手动执行此操作,则可以使用 OpenRewrite 提供的 UseStaticImport 访问器。应用于下面的文件,您可以看到这生成的更改。

// Before OpenRewrite
import org.junit.Assert;
...

Assert.assertTrue(condition);
// After OpenRewrite
import static org.junit.Assert.assertTrue;
...

assertTrue(condition);

后续步骤

3.2 - 在不修改构建的情况下在 Maven 项目上运行 Rewrite

在不修改构建的情况下在 Maven 项目上运行 Rewrite

https://docs.openrewrite.org/running-recipes/running-rewrite-on-a-maven-project-without-modifying-the-build

在本教程中,我们将应用 Rewrite recipe (配方)添加到使用 Maven 构建的源代码存储库中,而无需修改构建本身。根据配方是否具有配置参数,此说明略有不同。请注意,您需要先安装 Maven 以运行 shell 命令。

在没有配置参数的情况下运行配方

如果您尝试运行的配方没有任何必需的配置参数,则可以通过执行 shell 命令来运行配方。

我们 recipe 文档 包括针对任何没有配置参数的配方运行的特定 shell 命令。您可能会发现复制并运行提供的命令比手动创建它更容易。

如果配方来自core Rewrite库(如删除未使用的导入),然后您可以运行以下命令并将 org.openrewrite.java.RemoveUnusedImports 替换为要运行的配方的路径:

mvn -U org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.openrewrite.java.RemoveUnusedImports

如果配方来自不同的库(例如迁移到 Jakarta EE 9),然后您可以运行以下命令并将 org.openrewrite.recipe:rewrite-migrate-java:LATEST 替换为配方的工件,并将 org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta 替换为要运行的配方的路径:

mvn -U org.openrewrite.maven:rewrite-maven-plugin:run \
  -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-migrate-java:LATEST \
  -Drewrite.activeRecipes=org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta

使用配置参数运行配方

如果您尝试运行的配方具有配置参数,则需要:

  1. 在项目根目录中创建或更新 rewrite.yml 文件.在那里,您需要创建一个新配方,该配方包装要运行的配方并指定要使用的参数。

  2. 运行一个 shell 命令,该命令执行您在步骤 1 中定义的新配方。

例如,如果你想运行 ChangePackage 配方 若要将 org.old.package.name 更改为 org.new.package.name,需要创建一个如下所示的 rewrite.yml 文件:

---
type: specs.openrewrite.org/v1beta/recipe
name: com.yourorg.NameYouDefine
recipeList:
  - org.openrewrite.java.ChangePackage:
      oldPackageName: org.old.package.name
      newPackageName: org.new.package.name

然后,您可以通过执行以下 shell 命令来运行该配方:

mvn -U org.openrewrite.maven:rewrite-maven-plugin:run \
  -Drewrite.activeRecipes=com.yourorg.NameYouDefine