Ubuntu 22.04 安装 Apache Commons Configuration 指南
在 Ubuntu 22.04 搭建 Apache Commons Configuration 2.15.1:JDK 17 与 Maven 安装、依赖与发行包双方案、sha512 校验、最小验证代码、多版本管理与卸载,回显实测。
Ubuntu 22.04 安装 Apache Commons Configuration 指南
目标:在 Ubuntu 22.04 服务器上从零搭建可编译、可运行 Apache Commons Configuration 2.x 的 Java 环境,覆盖「Maven 中央仓库依赖」与「官方发行包手动安装」两种方案、sha512 完整性校验、最小验证代码、多版本管理与卸载,已在 Ubuntu 22.04(OpenJDK 17 + Maven 3.6.3)实测通过。
一、环境信息
本篇所有命令与回显均在以下环境中实测采集,复现时请保持相近版本:
- 操作系统:Ubuntu 22.04(jammy),x86_64
- JDK:OpenJDK 17.0.20.1(
openjdk-17-jdk,apt 官方仓库) - 构建工具:Apache Maven 3.6.3(
maven,apt 官方仓库) - 组件版本:Apache Commons Configuration 2.15.1(2.x 线当前最新版,2026-10 实测)
- 下载与校验工具:curl、tar、sha512sum(coreutils)
- 实验目录:
/opt/commons-config(Maven 工程/opt/commons-config/demo,手动安装目录/opt/commons-config/install) - 执行用户:root
二、前置条件
本节确认系统版本、网络可达性与基础工具,保证后续下载与依赖解析能顺利完成。
2.1 确认系统与架构
cat /etc/os-release | head -2
回显(实测):
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"
uname -m
回显(实测):
x86_64
2.2 确认外网可达
Apache Commons Configuration 的官方发行包托管在 downloads.apache.org,Maven 依赖解析需要访问 repo1.maven.org:
curl -sI https://downloads.apache.org/ | head -3
回显(实测):
HTTP/2 200
date: Tue, 13 Oct 2026 08:19:02 GMT
server: Apache
curl -sI https://repo1.maven.org/maven2/ | head -2
回显(实测):
HTTP/2 200
date: Tue, 13 Oct 2026 08:19:15 GMT
2.3 安装基础工具
全新 Ubuntu 22.04 最小安装默认没有 curl,先补齐(tar、sha512sum 属于 base 包组,无需单独安装):
apt-get install -y curl
回显(实测节选,首尾):
Reading package lists... Done
Building dependency tree... Done
...
Setting up curl (7.81.0-2ubuntu1.21) ...
Processing triggers for libc-bin (2.35-0ubuntu3.15) ...
验证工具就绪:
which curl tar sha512sum
回显(实测):
/usr/bin/curl
/usr/bin/tar
/usr/bin/sha512sum
三、版本选型
Commons Configuration 存在 1.x 与 2.x 两条版本线,二者 Maven 坐标(GAV)不同、包名不同、API 不兼容,动手安装前必须先选对线。
3.1 1.x 与 2.x 对比
| 对比项 | 1.x 线 | 2.x 线(本篇选用) |
|---|---|---|
| Maven GAV | commons-configuration:commons-configuration | org.apache.commons:commons-configuration2 |
| 最新版本 | 1.10(2014 年后仅维护,已 EOL) | 2.15.1(2026-10 实测最新) |
| Java 包名 | org.apache.commons.configuration | org.apache.commons.configuration2 |
| JDK 要求 | Java 5+ | Java 8+(RELEASE-NOTES 明确 requires Java 8),兼容 JDK 17 |
| 核心 API | PropertiesConfiguration("文件名") 直连构造器 | 构造器 + FileHandler/Configurations/Builder(1.x 直连构造器已移除) |
| YAML/JSON 支持 | 无 | YAMLConfiguration/JSONConfiguration(需额外依赖) |
| 官方仓库 | downloads.apache.org commons-configuration-1.10 | downloads.apache.org commons-configuration2-2.15.1 |
💡 技术拓展:Commons Configuration 支持的配置来源对比
配置源 语法风格 层级结构 类型推断 热更新 properties key=value 点分扁平 弱(字符串) 支持(文件检测重载) XML 标签/属性 天然树形 弱 支持 JSON 对象/数组 树形 数字/布尔保留 支持 YAML 缩进 树形 数字/布尔保留 支持 INI section 分组 两组层级 弱 支持 环境变量 进程环境 扁平 弱 不支持(进程生命周期内不变) JNDI JNDI 名 树形 弱 取决于 JNDI 服务 数据库 表行 扁平 弱 支持(每次查询) 本文主线为 properties 与 XML(最常用、依赖最少),YAML/JSON 作为扩展在依赖清单中说明。
3.2 Java 配置库横向对比
💡 技术拓展:如果项目尚未确定用哪个配置库,可参考下表定位 Commons Configuration2 的位置。本文选用 Commons Configuration2。
库 归属 多格式支持 变量插值 动态重载 适用场景 JDK java.util.PropertiesJDK 自带 仅 properties 无 无 单文件、零依赖 Spring EnvironmentSpring 生态 随框架 ${key}占位符配合 Spring 实现 Spring/Spring Boot 项目 Typesafe Config(Lightbend config) Akka/Play 系 properties/JSON/HOCON 是 无内置 JVM 通用、HOCON 语法偏好 Commons Configuration2 Apache Commons properties/XML/JSON/YAML/INI/JNDI/DB 等 ${prefix:key}内建 ReloadingController 独立运行的 Java 程序、多源组合
表中 ${prefix:key} 指 Commons Configuration2 的变量插值语法:配置文件里写 ${env:HOME},读取时自动解析为当前用户主目录(实验机实测 /root);写 ${sys:java.home} 解析为 JDK 安装目录。Spring 行的 ${key} 是 Spring 自身的占位符机制,与本文组件无关。
选型结论:需要在非 Spring 环境下统一管理多格式配置文件并支持自动重载时,Commons Configuration2 是 Apache 官方维护、依赖轻量的选择,本篇按 2.15.1 安装。
四、方案 A:Maven 中央仓库依赖(推荐)
Maven 会自动下载主 jar 与全部必选传递依赖,是绝大多数 Java 项目的标准做法。
4.1 安装 JDK 17 与 Maven
apt-get update && apt-get install -y openjdk-17-jdk maven
回显(实测节选,首尾):
Get:1 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 openjdk-17-jdk-headless all 17.0.20.1+1-1~22.04 [71.2 kB]
...
Setting up maven (3.6.3-5) ...
Processing triggers for man-db (2.10.2-1) ...
验证安装结果:
java -version
回显(实测):
openjdk version "17.0.20.1" 2026-08-18
OpenJDK Runtime Environment (build 17.0.20.1+1-1-22.04-Ubuntu)
OpenJDK 64-Bit Server VM (build 17.0.20.1+1-1-22.04-Ubuntu, mixed mode, sharing)
mvn -version
回显(实测):
Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 17.0.20.1, vendor: Ubuntu, runtime: /usr/lib/jvm/java-17-openjdk-amd64
Default locale: en_US, platform encoding: ANSI_X3.4-1968
OS name: "linux", version: "6.8.0-138-generic", arch: "amd64", family: "unix"
注意回显中的
platform encoding: ANSI_X3.4-1968:这是系统未配置 UTF-8 locale 时的平台编码,会导致含中文的源码/配置处理异常,可用export JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8或安装language-pack-zh-hans修正,详见 FAQ Q5。
4.2 创建工程并添加依赖
创建工程目录与 pom.xml:
mkdir -p /opt/commons-config/demo/src/main/java/com/example
cd /opt/commons-config/demo
写入 pom.xml(内容如下,注意 GAV 是 commons-configuration2 而非 1.x 的 commons-configuration):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>config-demo</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-configuration2</artifactId>
<version>2.15.1</version>
</dependency>
</dependencies>
</project>
4.3 确认传递依赖清单
mvn dependency:tree 2>/dev/null | grep -E ':compile|:runtime'
回显(实测):
[INFO] \- org.apache.commons:commons-configuration2:jar:2.15.1:compile
[INFO] +- org.apache.commons:commons-lang3:jar:3.20.0:compile
[INFO] +- org.apache.commons:commons-text:jar:1.15.0:compile
[INFO] +- commons-logging:commons-logging:jar:1.3.6:compile
[INFO] \- commons-io:commons-io:jar:2.22.0:compile
Maven 传递依赖共 4 个:commons-lang3 3.20.0、commons-text 1.15.0、commons-logging 1.3.6、commons-io 2.22.0。官方 pom 中 commons-beanutils 1.11.0、snakeyaml 2.6、jackson-databind 2.21.3 等标记为 <optional>true</optional>,不会随 Maven 传递引入;若使用 Parameters/Builder API 需要显式补充 commons-beanutils,若加载 YAML/JSON 需要补充 snakeyaml/jackson-databind,详见 FAQ Q2、Q3。
4.4 编译打包
mvn package
回显(实测节选,尾):
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 14.559 s
[INFO] Finished at: 2026-10-13T08:28:26Z
[INFO] ------------------------------------------------------------------------
方案 A 环境到此可用。
4.5 最小验证代码
在工程中新建 src/main/java/com/example/QuickStart.java(2.x 惯用法:PropertiesConfiguration + FileHandler 加载与保存):
package com.example;
import java.io.FileWriter;
import java.util.Properties;
import org.apache.commons.configuration2.Configuration;
import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.io.FileHandler;
public class QuickStart {
public static void main(String[] args) throws ConfigurationException, java.io.IOException {
// 先手工生成一份 app.properties 作为演示数据
Properties p = new Properties();
p.setProperty("db.url", "jdbc:mysql://localhost:3306/demo");
p.setProperty("db.user", "root");
p.setProperty("db.pool.maxTotal", "20");
try (FileWriter w = new FileWriter("app.properties")) {
p.store(w, "generated by QuickStart");
}
// 2.x 的读取方式:PropertiesConfiguration + FileHandler
PropertiesConfiguration props = new PropertiesConfiguration();
FileHandler handler = new FileHandler(props);
handler.setFileName("app.properties");
handler.load();
Configuration cfg = props;
System.out.println("db.url = " + cfg.getString("db.url"));
System.out.println("db.user = " + cfg.getString("db.user"));
System.out.println("db.pool.maxTotal = " + cfg.getInt("db.pool.maxTotal"));
System.out.println("not.exist = " + cfg.getString("not.exist", "default"));
// 修改并保存,再从磁盘重新加载验证
cfg.setProperty("db.user", "admin");
handler.save();
handler.load();
System.out.println("after save, db.user = " + cfg.getString("db.user"));
}
}
用 Maven 产出的 classpath 编译运行(dependency:build-classpath 把 4 个传递依赖 jar 路径写入 /tmp/cp.txt):
cd /opt/commons-config/demo
mvn -q compile
mvn -q dependency:build-classpath -Dmdep.outputFile=/tmp/cp.txt
java -cp "target/classes:$(cat /tmp/cp.txt)" com.example.QuickStart
回显(实测):
db.url = jdbc:mysql://localhost:3306/demo
db.user = root
db.pool.maxTotal = 20
not.exist = default
after save, db.user = admin
五、方案 B:官方发行包手动安装
适合没有 Maven、无法连中央仓库(或希望离线部署 jar)的服务器。关键点:除主 jar 外,必须把 4 个必选传递依赖一并放入 classpath。
5.1 建立目录结构
mkdir -p /opt/commons-config/install/{downloads,lib-min,src/com/example,classes}
cd /opt/commons-config/install
命令无输出,确认目录已建:
ls /opt/commons-config/install
回显(实测):
classes downloads lib-min src
5.2 下载发行包并校验 sha512
cd /opt/commons-config/install/downloads
curl -SLO https://downloads.apache.org/commons/configuration/binaries/commons-configuration2-2.15.1-bin.tar.gz
curl -SLO https://downloads.apache.org/commons/configuration/binaries/commons-configuration2-2.15.1-bin.tar.gz.sha512
ls -l
回显(实测):
total 8260
-rw-r--r-- 1 root root 8450472 Oct 13 08:21 commons-configuration2-2.15.1-bin.tar.gz
-rw-r--r-- 1 root root 129 Oct 13 08:21 commons-configuration2-2.15.1-bin.tar.gz.sha512
.sha512 文件内容是裸哈希(没有文件名后缀),直接 sha512sum -c 会报 no properly formatted SHA512 checksum lines found,需要手工拼接成「哈希 + 两个空格 + 文件名」格式再校验:
echo "$(cat commons-configuration2-2.15.1-bin.tar.gz.sha512) commons-configuration2-2.15.1-bin.tar.gz" | sha512sum -c -
回显(实测):
commons-configuration2-2.15.1-bin.tar.gz: OK
5.3 解压发行包
cd /opt/commons-config/install
tar xzf downloads/commons-configuration2-2.15.1-bin.tar.gz
ls commons-configuration2-2.15.1/
回显(实测):
LICENSE.txt
NOTICE.txt
RELEASE-NOTES.txt
apidocs
commons-configuration2-2.15.1-javadoc.jar
commons-configuration2-2.15.1-sources.jar
commons-configuration2-2.15.1-test-sources.jar
commons-configuration2-2.15.1-tests.jar
commons-configuration2-2.15.1.jar
把主 jar 复制到 lib-min,再从 Maven 中央仓库补齐 4 个必选依赖 jar:
cd /opt/commons-config/install
cp commons-configuration2-2.15.1/commons-configuration2-2.15.1.jar lib-min/
B=https://repo1.maven.org/maven2
cd lib-min
curl -sSLO "$B/org/apache/commons/commons-lang3/3.20.0/commons-lang3-3.20.0.jar"
curl -sSLO "$B/org/apache/commons/commons-text/1.15.0/commons-text-1.15.0.jar"
curl -sSLO "$B/commons-logging/commons-logging/1.3.6/commons-logging-1.3.6.jar"
curl -sSLO "$B/commons-io/commons-io/2.22.0/commons-io-2.22.0.jar"
ls -l
回显(实测):
total 2308
-rw------- 1 root root 689129 Oct 13 08:22 commons-configuration2-2.15.1.jar
-rw-r--r-- 1 root root 609182 Oct 13 08:22 commons-io-2.22.0.jar
-rw-r--r-- 1 root root 713862 Oct 13 08:22 commons-lang3-3.20.0.jar
-rw-r--r-- 1 root root 74010 Oct 13 08:22 commons-logging-1.3.6.jar
-rw-r--r-- 1 root root 264873 Oct 13 08:22 commons-text-1.15.0.jar
以上 5 个 jar 就是 FileHandler 直连路线的最小运行时依赖(Parameters/Builder 路线还要追加 commons-beanutils-1.11.0.jar,见 FAQ Q2)。
5.4 编译与运行最小验证代码
把 4.5 节的 QuickStart.java 放到 src/com/example/ 后执行:
cd /opt/commons-config/install
javac -encoding UTF-8 -cp "lib-min/*" -d classes src/com/example/QuickStart.java
java -cp "classes:lib-min/*" com.example.QuickStart
回显(实测):
db.url = jdbc:mysql://localhost:3306/demo
db.user = root
db.pool.maxTotal = 20
not.exist = default
after save, db.user = admin
方案 B 环境验证通过。
六、两种方案对比与选型建议
| 对比项 | 方案 A:Maven 依赖 | 方案 B:发行包手动安装 |
|---|---|---|
| 依赖获取 | 自动解析 4 个必选传递依赖 | 手工下载 5 个 jar(主 jar + 4 依赖) |
| 版本升级 | 改 pom 版本号即可 | 重新下载并替换 jar |
| 离线部署 | 需私服或预先填充本地仓库 | 天然支持 |
| 附加格式(YAML/JSON) | 显式加 snakeyaml/jackson-databind 依赖 | 手工补 jar |
| 适用场景 | 常规 Java 工程、持续集成 | 遗留构建脚本、离线服务器、排查依赖问题 |
选型建议:工程内使用一律走方案 A;方案 B 用于离线交付、快速验证或作为方案 A 故障时的兜底。两套目录可共存(本篇 demo/ 与 install/ 互不影响)。
七、多版本管理
7.1 JDK 多版本切换
Ubuntu 的 apt 方式安装会注册 alternatives,先看本机现有 JDK(本机曾装过 JDK 11):
update-alternatives --list java
回显(实测):
/usr/lib/jvm/java-11-openjdk-amd64/bin/java
/usr/lib/jvm/java-17-openjdk-amd64/bin/java
交互式切换:
update-alternatives --config java
回显(实测节选):
There are 2 choices for the alternative java (providing /usr/bin/java).
Selection Path Priority Status
------------------------------------------------------------
0 /usr/lib/jvm/java-17-openjdk-amd64/bin/java 1711 auto mode
1 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1111 manual mode
* 2 /usr/lib/jvm/java-17-openjdk-amd64/bin/java 1711 manual mode
非交互式直接切换到 17:
update-alternatives --set java /usr/lib/jvm/java-17-openjdk-amd64/bin/java
java -version 2>&1 | head -1
回显(实测):
openjdk version "17.0.20.1" 2026-08-18
7.2 Commons Configuration 多版本 jar 共存
2.x 与 1.x 的包名不同(configuration2 vs configuration),两个版本可以同机共存、甚至同进程共引。建议按目录隔离:
mkdir -p /opt/commons-config/lib-1.10 /opt/commons-config/lib-2.15.1
cp /opt/commons-config/install/commons-configuration2-2.15.1/commons-configuration2-2.15.1.jar /opt/commons-config/lib-2.15.1/
ls /opt/commons-config/
回显(实测):
demo install lib-1.10 lib-2.15.1
同一工程内不建议同时引入 1.x 与 2.x(无冲突但徒增体积),迁移期建议单引 2.x 并按 FAQ Q1 调整代码。
八、常见问题(FAQ)
Q1:照 1.x 教程写 new PropertiesConfiguration("app.properties") 编译报错?
2.x 移除了 1.x 的直连构造器与实例 save() 方法,报错如下(实测):
[ERROR] /opt/commons-config/demo/src/main/java/com/example/QuickStart.java:[18,29] constructor PropertiesConfiguration in class org.apache.commons.configuration2.PropertiesConfiguration cannot be applied to given types;
[ERROR] required: no arguments
[ERROR] found: java.lang.String
[ERROR] /opt/commons-config/demo/src/main/java/com/example/QuickStart.java:[24,40] cannot find symbol
[ERROR] symbol: method save()
解法:2.x 统一走 FileHandler(加载与保存)或 Configurations(一次性读取)。正确写法:
PropertiesConfiguration props = new PropertiesConfiguration();
FileHandler handler = new FileHandler(props);
handler.setFileName("app.properties");
handler.load(); // 读取
handler.save(); // 保存
Q2:调用 Parameters/Builder API 报 NoClassDefFoundError: org/apache/commons/beanutils/BeanIntrospector?
commons-beanutils 在官方 pom 中是 <optional> 依赖,Maven 不会传递引入,但 fluent Parameters 工厂(含 new Parameters().xml() 等全部 builder 参数)运行期需要它。报错原文(实测):
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/beanutils/BeanIntrospector
at org.apache.commons.configuration2.builder.fluent.Parameters.createParametersProxy(Parameters.java:174)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.beanutils.BeanIntrospector
解法:Maven 工程显式添加依赖 commons-beanutils:commons-beanutils:1.11.0;手动 classpath 追加 commons-beanutils-1.11.0.jar(仅用 FileHandler 直连则不需要)。
Q3:加载 YAML/JSON 报 NoClassDefFoundError?
YAMLConfiguration 需要 org.yaml:snakeyaml:2.6,JSONConfiguration 需要 com.fasterxml.jackson.core:jackson-databind(官方 pom 版本 2.21.3,运行时还需 jackson-core 2.21.3 与 jackson-annotations 2.21)。报错样例(实测,无 snakeyaml 时):
Exception in thread "main" java.lang.NoClassDefFoundError: org/yaml/snakeyaml/constructor/BaseConstructor
注意:Maven 中央仓库中 jackson-annotations 没有 2.21.3 版本(Jackson 自 2.20 起 annotations 不再带 patch 号,返回 404),手动组 classpath 时应下载 jackson-annotations-2.21.jar。
Q4:properties 文件里的中文读出来是乱码?
PropertiesConfiguration.DEFAULT_ENCODING 是 ISO-8859-1(遵循 JDK Properties 规范),GBK 编码的历史文件按默认编码读取会乱码。实测对比(同一文件分别按默认编码与 GBK 读取):
默认编码 app.title = ��������
默认编码 app.owner = ��άƽ̨��
GBK 读取 app.title = 订单服务
GBK 读取 app.owner = 运维平台组
解法:Builder 参数加 setEncoding("GBK")(或把文件统一转存为 UTF-8 并显式 setEncoding("UTF-8"))。XML 同理,保存时不设编码会按平台默认字符集写出,中文注释会变 ?。
Q5:Maven 提示 platform encoding: ANSI_X3.4-1968,编译含中文注释的源码报 unmappable character?
系统未启用 UTF-8 locale。解法二选一:apt-get install -y language-pack-en && export LANG=C.UTF-8;或对 JVM 统一加 export JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8,并且 javac 始终带 -encoding UTF-8(本篇所有 javac 命令已带)。
九、卸载
9.1 卸载 Commons Configuration 本体
方案 A 工程直接删除目录并清理本地仓库缓存:
rm -rf /opt/commons-config/demo
rm -rf ~/.m2/repository/org/apache/commons/commons-configuration2
方案 B 手动安装删除安装目录:
rm -rf /opt/commons-config/install
若本地仓库中其余 org.apache.commons 构件也不再使用(如 commons-lang3 等),一并删除:
rm -rf ~/.m2/repository/org/apache/commons
rm -rf ~/.m2/repository/commons-logging
9.2 卸载 JDK 17 与 Maven(谨慎)
以下操作会影响同机其他 Java 程序,确认无共用需求后再执行:
apt-get purge -y maven && apt-get autoremove -y
回显(实测节选):
Removing maven (3.6.3-5) ...
Purging configuration files for maven (3.6.3-5) ...
(autoremove 阶段同步清理了 32 个随 maven 引入的依赖包。)
apt-get purge -y openjdk-17-jdk openjdk-17-jre && apt-get autoremove -y
回显(实测节选):
Removing openjdk-17-jdk:amd64 (17.0.20.1+1-1~22.04) ...
Removing openjdk-17-jre:amd64 (17.0.20.1+1-1~22.04) ...
执行后验证清理干净:
command -v java || echo "java 不存在"
command -v mvn || echo "mvn 不存在"
回显(实测):
java 不存在
mvn 不存在
十、参考链接
- Apache Commons Configuration 官网:https://commons.apache.org/proper/commons-configuration/
- 2.15.1 发行包下载目录:https://downloads.apache.org/commons/configuration/binaries/
- Maven 中央仓库坐标页:https://repo1.maven.org/maven2/org/apache/commons/commons-configuration2/2.15.1/
- 2.x 用户指南(User Guide):https://commons.apache.org/proper/commons-configuration/userguide/quick_start.html
- 2.x Javadoc(本机发行包内:
/opt/commons-config/install/commons-configuration2-2.15.1/apidocs/index.html):https://commons.apache.org/proper/commons-configuration/apidocs/index.html - JDK 17 安装包页(Ubuntu 包索引):https://packages.ubuntu.com/jammy/openjdk-17-jdk