CentOS 8 安装 Apache Commons Collections 指南
在 CentOS 8 从零安装 Apache Commons Collections 4.6.0:dnf 装 JDK、tarball 装 Maven、Maven 依赖与手动 bin 包两种方案、多版本管理与卸载,全程实测回显。
CentOS 8 安装 Apache Commons Collections 指南
目标:在 CentOS 8 上从零搭建一个能编译、能运行 Apache Commons Collections(commons-collections4)4.6.0 的 Java 环境,覆盖 JDK/Maven 安装、Maven 依赖与手动下载 bin 包两种接入方案、JDK 多版本管理与卸载清理。已在 CentOS Linux 8(x86_64、OpenJDK 17.0.1、Maven 3.9.16)实测通过。
一、环境信息
本篇所有命令均在以下环境中实际执行并回显,CentOS 8 已于 2021 年底停止维护,实测主机软件源已指向 vault 归档仓库,命令在全新机器上需先完成同样的源配置。
- 操作系统:CentOS Linux 8(x86_64),软件源 mirrors.tuna.tsinghua.edu.cn/centos-vault/8.5.2111
- JDK:OpenJDK 17.0.1(java-17-openjdk,另演示安装 java-11-openjdk 11.0.13)
- 构建工具:Apache Maven 3.9.16(tarball 安装于 /opt/apache-maven-3.9.16)
- 目标库:Apache Commons Collections 4.6.0(Maven 坐标 org.apache.commons:commons-collections4)
- 工作目录:/root/collections-lab
- 依赖网络:downloads.apache.org、dlcdn.apache.org、repo.maven.apache.org 直连可达
二、版本选型与前置要求
Commons Collections 是 JDK 内置集合框架之外的集合扩展库,补齐 Bag(计数集合)、BidiMap(双向映射)、MultiValuedMap(一键多值)、Trie(前缀树)等结构。选型时按「版本系列 + JDK 要求」两个维度定:
💡 技术拓展:Java 集合扩展库不止本文选用的 Apache Commons Collections,主流选项对比——
库 定位/特点 适用场景 JDK 内置 java.util 官方标准集合,List/Set/Map 稳定通用 绝大多数普通业务 Apache Commons Collections 补充 Bag/BidiMap/MultiValuedMap/Trie/谓词装饰器等结构 需要 JDK 缺失的集合结构与函数式工具 Guava Google 工具集,Multiset/Multimap/Range/Table 与不可变集合 已引入 Guava 生态的项目 Eclipse Collections 高性能、内存优化,含原始类型(int/long)专用集合 大数据量、性能与内存敏感 本文选用 Apache Commons Collections 4.6.0:单 jar 零传递依赖,官方 bin 包与 Maven 中央仓库均可直接获取,JDK 8+ 全兼容,与 CentOS 8 上的 OpenJDK 8/11/17 均可搭配。
2.1 版本选型表
以官方发布目录(downloads.apache.org/commons/collections/)为准,2026 年 10 月时 4.x 最新版为 4.6.0:
| 版本 | 发布日期 | 包名 | 最低 JDK | 状态说明 |
|---|---|---|---|---|
| 3.2.2 | 2015-11-14 | org.apache.commons.collections | Java 5+ | 3.x 最终版,已 EOL,存在反序列化漏洞历史(见 FAQ) |
| 4.4 | 2019-07-09 | org.apache.commons.collections4 | Java 8+ | 4.x 稳定老版本,存量项目常见 |
| 4.5.0 | 2025-04-22 | org.apache.commons.collections4 | Java 8+ | 4.x 过渡版本 |
| 4.6.0 | 2026-08-10 | org.apache.commons.collections4 | Java 8+ | 当前官方最新,本篇实测版本 |
关键差异:3.x 包名 org.apache.commons.collections 与 4.x 的 org.apache.commons.collections4 二进制不兼容,新项目一律 4.6.0;3.x 已 EOL 且有反序列化漏洞利用史,老项目应尽快迁移。4.6.0 官方 RELEASE-NOTES 明确「Java 8 or later is required」,CentOS 8 的 java-8-openjdk、java-11-openjdk、java-17-openjdk 均满足,本篇主线用 17,第六节演示 11/17 共存。
2.2 前置要求
- JDK 8 及以上:编译与运行都需要 JDK(javac),仅装 headless 运行包无法编译示例。
- root 权限:dnf 安装、写 /opt 与 /usr/local/bin。
- CentOS 8 已 EOL,软件源需指向 vault 归档(本机 /etc/yum.repos.d/CentOS-Linux-*.repo 已配置 baseurl 为 mirrors.tuna.tsinghua.edu.cn/centos-vault/8.5.2111),否则 dnf 会因 mirrorlist.centos.org 失效而报错。
三、安装 JDK 17
先确认 17 已安装。OpenJDK 17 在 CentOS 8 的 AppStream 仓库中,用 dnf 安装并保证 devel 子包(提供 javac)到位:
sudo dnf install -y java-17-openjdk java-17-openjdk-devel
java -version
javac -version
实测回显(本机 17 已是最新,全新机器会先下载安装再输出同样版本号):
Dependencies resolved.
Nothing to do.
Complete!
openjdk version "17.0.1" 2021-10-19 LTS
OpenJDK Runtime Environment 21.9 (build 17.0.1+12-LTS)
OpenJDK 64-Bit Server VM 21.9 (build 17.0.1+12-LTS, mixed mode, sharing)
javac 17.0.1
验证要点:java 与 javac 版本号都出现即满足编译与运行两个前提。
四、安装 Maven 3.9.16
与 Ubuntu 一致,采用官方 tarball 安装。下载并做 sha512 校验(校验值取自官方 .sha512 文件,注意该文件只有散列值没有文件名,需自行拼接校验行):
mkdir -p /tmp/mvn-c8 && cd /tmp/mvn-c8
curl -sSOL https://dlcdn.apache.org/maven/maven-3/3.9.16/binaries/apache-maven-3.9.16-bin.tar.gz
echo "831a8591fe20c8243b1dbe7d71e3244f31d1665b0804b2e825e38cbbe5ce0cafb8338851f90780735568773e0a6cd07bbec107cda0b896b008b861075358b6f6 apache-maven-3.9.16-bin.tar.gz" | sha512sum -c -
实测回显:
apache-maven-3.9.16-bin.tar.gz: OK
解压到 /opt 并软链 mvn 到 /usr/local/bin,然后验证:
sudo tar xzf apache-maven-3.9.16-bin.tar.gz -C /opt
sudo ln -sf /opt/apache-maven-3.9.16/bin/mvn /usr/local/bin/mvn
mvn -version
实测回显:
Apache Maven 3.9.16 (2bdd9fddda4b155ebf8000e807eb73fd829a51d5)
Maven home: /opt/apache-maven-3.9.16
Java version: 17.0.1, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-17-openjdk-17.0.1.0.12-2.el8_5.x86_64
验证要点:Maven home 指向 /opt/apache-maven-3.9.16,Java version 识别为 Red Hat vendor 的 17.0.1 即成功。Maven 本地仓库在 ~/.m2/repository。
五、获取 commons-collections4 的两种方案
与所有 Java 库一样,接入方式两种:方案A Maven 声明依赖;方案B 手动下载官方 bin 包后 javac/java -cp 直跑。两方案均给出从零到跑通的完整命令。
5.1 方案A:Maven 依赖接入(推荐)
创建最小工程并写入 pom.xml 与验证程序:
mkdir -p /root/collections-lab/maven-demo/src/main/java/com/example
cd /root/collections-lab/maven-demo
<?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>collections-demo</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.6.0</version>
</dependency>
</dependencies>
</project>
配置说明:dependency 坐标 org.apache.commons:commons-collections4:4.6.0 即目标库,scope 缺省 compile;compiler.source/target 压到 8 保证产物在 JDK 8+ 全兼容;sourceEncoding=UTF-8 防中文源码乱码。验证程序 src/main/java/com/example/CollectionDemo.java:
package com.example;
import org.apache.commons.collections4.Bag;
import org.apache.commons.collections4.bag.HashBag;
public class CollectionDemo {
public static void main(String[] args) {
Bag<String> bag = new HashBag<>();
bag.add("apple", 3);
bag.add("banana");
System.out.println("collections4 works! bag = " + bag);
System.out.println("getCount(apple) = " + bag.getCount("apple"));
}
}
编译(首次运行会从中央仓库下载依赖与插件,实测本机缓存冷启动用时约 21 秒):
mvn compile
实测输出节选(实测首尾):
[INFO] /root/collections-lab/maven-demo/src/main/java/com/example/CollectionDemo.java: /root/collections-lab/maven-demo/src/main/java/com/example/CollectionDemo.java uses or overrides a deprecated API.
[INFO] BUILD SUCCESS
[INFO] Total time: 21.169 s
[INFO] Finished at: 2026-10-13T05:06:27Z
INFO 行的 deprecated 提醒指向 HashBag 在 4.6.0 被标记过时(FAQ Q2),不影响构建。复制依赖 jar 并运行:
mvn dependency:copy-dependencies -DoutputDirectory=target/dep
ls target/dep/
java -cp target/classes:target/dep/\* com.example.CollectionDemo
实测回显:
commons-collections4-4.6.0.jar
collections4 works! bag = [1:banana,3:apple]
getCount(apple) = 3
[1:banana,3:apple] 即 HashBag 的 元素:计数 展示,出现这两行说明全链路可用。
5.2 方案B:手动下载 bin 包 + javac/java -cp 直跑
下载官方 bin 包并校验(sha512 实测值 b54c6173 开头、d3aa5 结尾):
mkdir -p /root/collections-lab/manual && cd /root/collections-lab/manual
curl -sSOL https://downloads.apache.org/commons/collections/binaries/commons-collections4-4.6.0-bin.tar.gz
echo "b54c61737ff2ec7eaf6e1caf4d2adae42534dd28a9383c3fae1d5f299bce97b00ca15aee2c81ba4a4b50e64db69103cc3629a43af39b52f90990cdee944d3aa5 commons-collections4-4.6.0-bin.tar.gz" | sha512sum -c -
tar xzf commons-collections4-4.6.0-bin.tar.gz
ls commons-collections4-4.6.0/
实测回显:
commons-collections4-4.6.0-bin.tar.gz: OK
LICENSE.txt
NOTICE.txt
RELEASE-NOTES.txt
apidocs
commons-collections4-4.6.0-javadoc.jar
commons-collections4-4.6.0-sources.jar
commons-collections4-4.6.0-test-sources.jar
commons-collections4-4.6.0-tests.jar
commons-collections4-4.6.0.jar
写验证程序 HelloCollections.java 并编译运行:
import org.apache.commons.collections4.Bag;
import org.apache.commons.collections4.bag.HashBag;
public class HelloCollections {
public static void main(String[] args) {
Bag<String> bag = new HashBag<>();
bag.add("apple", 3);
bag.add("banana");
System.out.println("Hello commons-collections4! bag = " + bag);
}
}
javac -cp commons-collections4-4.6.0/commons-collections4-4.6.0.jar HelloCollections.java
java -cp .:commons-collections4-4.6.0/commons-collections4-4.6.0.jar HelloCollections
实测回显:
Hello commons-collections4! bag = [1:banana,3:apple]
5.3 方案对比与选型建议
| 维度 | 方案A:Maven 依赖 | 方案B:手动 bin 包 |
|---|---|---|
| 获取方式 | pom 声明坐标,mvn 自动下载 | curl 下载 bin tar.gz,sha512 校验 |
| 版本升级 | 改 pom version 一处 | 重新下载解压并改 -cp |
| 传递依赖 | 自动管理(本库无传递依赖) | 手动处理 |
| 适用场景 | 常规工程、持续集成 | 无 Maven 机器、脚本验证、离线环境 |
| 依赖 jar 位置 | ~/.m2/repository 与 target/dep | 任意自选目录 |
关键差异:本库是零传递依赖单 jar,方案B几乎零维护成本;工程化项目选方案A,交给 Maven 管版本与缓存。两方案在同一台机器可并存。
六、JDK 多版本管理(11 与 17 共存)
CentOS 8 用 alternatives 体系管理多 JDK。安装 java-11-openjdk 双包(headless 提供运行时、devel 提供编译器):
sudo dnf install -y java-11-openjdk java-11-openjdk-devel
实测输出节选(实测首尾):
java-11-openjdk-devel-1:11.0.13.0.8-4.el8_5.x86_64
java-11-openjdk-headless-1:11.0.13.0.8-4.el8_5.x86_64
Complete!
确认 /usr/lib/jvm 下两个版本目录并存,并用 JAVA_HOME 会话级切换(不改动系统默认,避免影响其他服务):
ls /usr/lib/jvm/
export JAVA_HOME=/usr/lib/jvm/java-11
export PATH=$JAVA_HOME/bin:$PATH
java -version
实测回显:
java
java-11
java-11-openjdk
java-11-openjdk-11.0.13.0.8-4.el8_5.x86_64
java-17
java-17-openjdk
java-17-openjdk-17.0.1.0.12-2.el8_5.x86_64
openjdk version "11.0.13" 2021-10-19 LTS
OpenJDK Runtime Environment 18.9 (build 11.0.13+8-LTS)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.13+8-LTS, mixed mode, sharing)
用 JDK 11 编译并运行同一个 HashBag 示例(先在 11 下重新编译,原因见下方注意)。示例 BagDemo11.java 源码:
import org.apache.commons.collections4.Bag;
import org.apache.commons.collections4.bag.HashBag;
public class BagDemo11 {
public static void main(String[] args) {
Bag<String> bag = new HashBag<>();
bag.add("apple", 3);
bag.add("banana");
bag.add("apple");
System.out.println("bag = " + bag);
System.out.println("getCount(apple) = " + bag.getCount("apple"));
}
}
javac -nowarn -cp commons-collections4-4.6.0/commons-collections4-4.6.0.jar BagDemo11.java
java -cp .:commons-collections4-4.6.0/commons-collections4-4.6.0.jar BagDemo11
javap -v BagDemo11.class | grep major
实测回显:
bag = [1:banana,4:apple]
getCount(apple) = 4
major version: 55
切回 17 的方式相同:export JAVA_HOME=/usr/lib/jvm/java-17,实测 java -version 回到 17.0.1。
⚠️ 注意:JDK 17 编译出的 class(major 61)在 JDK 11 上运行会报错,实测报错原文为「UnsupportedClassVersionError: BagDemo has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 55.0」。解法是同一 JDK 编译并运行,或按 5.1 的 pom 把 maven.compiler.source/target 固定为 8,产物在 8/11/17 通用。
七、卸载与清理
按逆序清理并逐步验证。删除示例与下载物:
rm -rf /root/collections-lab /tmp/mvn-c8
卸载演示用 JDK 11(生产需要 11 则跳过):
sudo dnf remove -y java-11-openjdk java-11-openjdk-devel
ls /usr/lib/jvm/
实测回显(11 相关目录已消失,仅剩 17 系列):
Complete!
java
java-17
java-17-openjdk
java-17-openjdk-17.0.1.0.12-2.el8_5.x86_64
java-openjdk
jre
jre-17
jre-17-openjdk
jre-17-openjdk-17.0.1.0.12-2.el8_5.x86_64
jre-openjdk
卸载 Maven:删软链与安装目录并验证:
sudo rm -f /usr/local/bin/mvn
sudo rm -rf /opt/apache-maven-3.9.16
command -v mvn
实测回显(无输出,mvn 已不在 PATH):
mvn: not found
如需连 JDK 17 一起移除:sudo dnf remove -y java-17-openjdk java-17-openjdk-devel,验证方式同上。~/.m2 缓存目录确认不再使用 Maven 后可删除。
八、常见问题 FAQ
Q1: dnf 报「Failed to download metadata for repo appstream」怎么办?CentOS 8 的官方镜像源 mirrorlist.centos.org 已下线。把 /etc/yum.repos.d/CentOS-Linux-*.repo 中的 mirrorlist 行注释掉,baseurl 指向归档仓库(本机实测指向 https://mirrors.tuna.tsinghua.edu.cn/centos-vault/8.5.2111/),再执行 dnf makecache 即可。
Q2: 3.x 还能用吗?3.x 包名是 org.apache.commons.collections,4.x 改为 org.apache.commons.collections4,二进制不兼容。安全方面:3.x 的 InvokerTransformer 等 functors 类实现了 Serializable,在 Java 反序列化场景被 ysoserial 的 CommonsCollections 系列利用链反复利用;4.1 起 functors 类不再实现 Serializable,从根源阻断了这条利用路径。3.x 已 EOL,新项目必须用 4.x(本篇 4.6.0)。
Q3: 编译 HashBag 时提示 deprecated?4.6.0 起官方把 Bag/HashBag 标记过时,推荐等价替代 MultiSet/HashMultiSet(4.6.0 RELEASE-NOTES 中 COLLECTIONS-893 补齐的能力),getCount 计数语义不变;老代码可继续用,新代码建议直接 HashMultiSet。
Q4: 不用 Maven 行吗?行,5.2 方案B就是官方 bin 包 + javac/java -cp 直跑,本库零传递依赖,-cp 只需挂一个 jar。
九、参考链接
- Apache Commons Collections 官方主页:https://commons.apache.org/proper/commons-collections/
- 官方发行包目录(含 sha512):https://downloads.apache.org/commons/collections/
- Maven 中央仓库 commons-collections4:https://mvnrepository.com/artifact/org.apache.commons/commons-collections4
- 4.6.0 RELEASE-NOTES:https://downloads.apache.org/commons/collections/RELEASE-NOTES.txt
- 历史版本归档(3.2.2 与 4.4 等日期依据):https://archive.apache.org/dist/commons/collections/binaries/
- Apache Maven 下载页:https://maven.apache.org/download.cgi