Ubuntu 22.04 安装 Apache Commons Collections 指南
在 Ubuntu 22.04 从零安装 Apache Commons Collections 4.6.0:Maven 依赖与手动 bin 包两种方案、JDK 多版本管理、最小验证程序与卸载清理,全程命令实测。
Ubuntu 22.04 安装 Apache Commons Collections 指南
目标:在 Ubuntu 22.04 上从零搭建一个能编译、能运行 Apache Commons Collections(commons-collections4)4.6.0 的 Java 环境,覆盖 JDK/Maven 安装、Maven 依赖与手动下载 bin 包两种接入方案、JDK 多版本管理与卸载清理。已在 Ubuntu 22.04.5 LTS(x86_64、OpenJDK 17.0.20.1、Maven 3.9.16)实测通过。
一、环境信息
本篇所有命令均在以下环境中实际执行并回显,读者按相同版本操作可获得一致结果。
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- JDK:OpenJDK 17.0.20.1(软件包 openjdk-17-jdk-headless,另演示安装 openjdk-11-jdk-headless)
- 构建工具: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。Commons Collections 是 JDK 内置集合框架之外的集合扩展库,为 Java 补充了 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 零传递依赖、结构类型最全,且实测官方下载与 Maven 中央仓库均可直接获取。
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 与 4.x 不能混用——3.x 的包名是 org.apache.commons.collections,4.x 改为 org.apache.commons.collections4,类与方法的泛型签名也有大量变化;新项目一律选 4.6.0,老项目若仍在 3.x 应尽快迁移(3.x 已停止维护且有著名的反序列化漏洞利用史)。4.6.0 官方 RELEASE-NOTES 明确写着「Java 8 or later is required」,因此 JDK 8/11/17/21 均可运行,本篇以 17 为主线并在第六节演示 11/17 共存。
2.2 前置要求
- JDK 8 及以上(本篇安装 17,另演示 11);编译与运行都需要 JDK 而非仅 JRE。
- root 或 sudo 权限:apt 安装软件包、写 /opt 与 /usr/local/bin。
- 网络可达 downloads.apache.org(官方发行包)与 repo.maven.apache.org(Maven 中央仓库)。
三、安装 JDK 17
JDK 是编译和运行 commons-collections4 程序的基础。先更新软件源索引,再安装 openjdk-17-jdk-headless 软件包:
sudo apt-get update
sudo apt-get install -y openjdk-17-jdk-headless
实测输出节选(本环境已装 17,重装命令会确认包状态,全新机器会执行下载安装):
Hit:2 http://security.ubuntu.com/ubuntu jammy-security InRelease
Hit:3 http://archive.ubuntu.com/ubuntu jammy-updates InRelease
openjdk-17-jdk-headless is already the newest version (17.0.20.1+1-1~22.04).
openjdk-17-jdk-headless set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.
验证 JDK 已就位(编译器 javac 必须同时存在,否则第五节无法编译示例):
java -version
javac -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)
javac 17.0.20.1
四、安装 Maven 3.9.16
方案A(Maven 依赖接入)需要一个可用的 Maven。Ubuntu 源里的 maven 包版本偏旧,这里采用官方 tarball 安装到 /opt,再做软链接进 PATH。先下载 3.9.16 并做 sha512 校验(校验值取自官方 .sha512 文件,实测内容为 831a8591 开头、b6f6 结尾,注意官方该文件只有散列值没有文件名,需自行拼接校验行):
mkdir -p /tmp/maven-demo && cd /tmp/maven-demo
curl -sSOL https://dlcdn.apache.org/maven/maven-3/3.9.16/binaries/apache-maven-3.9.16-bin.tar.gz
curl -sSO https://dlcdn.apache.org/maven/maven-3/3.9.16/binaries/apache-maven-3.9.16-bin.tar.gz.sha512
cat apache-maven-3.9.16-bin.tar.gz.sha512
echo "$(cat apache-maven-3.9.16-bin.tar.gz.sha512) apache-maven-3.9.16-bin.tar.gz" | sha512sum -c -
实测回显:
831a8591fe20c8243b1dbe7d71e3244f31d1665b0804b2e825e38cbbe5ce0cafb8338851f90780735568773e0a6cd07bbec107cda0b896b008b861075358b6f6
apache-maven-3.9.16-bin.tar.gz: OK
校验通过后解压到 /opt,并把 mvn 软链到 /usr/local/bin 使其在 PATH 中生效:
sudo tar xzf apache-maven-3.9.16-bin.tar.gz -C /opt
sudo ln -s /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.20.1, vendor: Ubuntu, runtime: /usr/lib/jvm/java-17-openjdk-amd64
验证要点:mvn -version 输出的 Maven home 指向 /opt/apache-maven-3.9.16、Java version 为 17.0.20.1,即说明软链与 JDK 识别都生效。Maven 依赖的本地仓库默认在 ~/.m2/repository,后续下载的 jar 都落在这里。
五、获取 commons-collections4 的两种方案
Commons Collections 本体只是一个 jar,接入项目有两种主流方式:方案A通过 Maven 声明依赖自动下载;方案B手动下载官方 bin 包,用 javac/java -cp 直跑。两种方案下面都给出从建目录到跑通验证程序的完整命令。
5.1 方案A:Maven 依赖接入(推荐)
先创建最小 Maven 工程:目录结构为 pom.xml 加 src/main/java 源码目录。
mkdir -p /root/collections-lab/maven-demo/src/main/java/com/example
cd /root/collections-lab/maven-demo
写入 pom.xml,核心是 dependencies 里的 commons-collections4 4.6.0 坐标:
<?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>
配置说明:groupId/artifactId/version 是本项目自身坐标;maven.compiler.source/target 设为 8 表示按 Java 8 字节码编译,与 commons-collections4 的最低要求对齐,可保证产物在 JDK 8+ 全兼容;project.build.sourceEncoding 固定 UTF-8,避免中文源码乱码;dependency 部分即目标库,scope 缺省为 compile。
写入最小验证程序 src/main/java/com/example/CollectionDemo.java,用 HashBag 做计数:
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"));
}
}
编译(首次执行会从中央仓库下载依赖与插件,网络慢时多等片刻):
mvn compile
实测输出节选(实测首尾):
[INFO] Building collections-demo 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] BUILD SUCCESS
[INFO] Total time: 0.683 s
[INFO] Finished at: 2026-10-13T04:59:43Z
把依赖 jar 复制到 target/dep,再用 java -cp 运行验证程序:
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 直跑
不使用 Maven 时,直接取官方 bin 包。下载 4.6.0 并用官方 sha512 校验(校验值 b54c61737ff2ec7eaf6e1caf4d2adae42534dd28a9383c3fae1d5f299bce97b00ca15aee2c81ba4a4b50e64db69103cc3629a43af39b52f90990cdee944d3aa5,实测来自 downloads.apache.org 的 .sha512 文件):
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
ls -lh commons-collections4-4.6.0-bin.tar.gz
echo "b54c61737ff2ec7eaf6e1caf4d2adae42534dd28a9383c3fae1d5f299bce97b00ca15aee2c81ba4a4b50e64db69103cc3629a43af39b52f90990cdee944d3aa5 commons-collections4-4.6.0-bin.tar.gz" | sha512sum -c -
实测回显:
-rw-r--r-- 1 root root 12M Oct 13 05:00 commons-collections4-4.6.0-bin.tar.gz
commons-collections4-4.6.0-bin.tar.gz: OK
解压并确认 jar 位置:
tar xzf commons-collections4-4.6.0-bin.tar.gz
ls commons-collections4-4.6.0/
实测回显:
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
bin 包除主 jar 外还带 javadoc/sources 两个 jar 与离线 apidocs 目录,主 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);
}
}
编译并运行(-cp 同时指定当前目录与目标 jar):
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
实测回显(javac 有一条 Bag 已标记过时的提醒,含义见 FAQ Q2,不影响运行):
Note: HelloCollections.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
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的 -cp 维护成本接近于零,非常适合脚本与教学;但凡项目规模成长到需要统一构建,选方案A,版本管理与仓库缓存都由 Maven 托管。本篇后续章节两种环境均保留可用。
六、JDK 多版本管理(11 与 17 共存)
commons-collections4 4.6.0 只要求 Java 8+,实际生产常出现「新项目 17、老项目 11」并存。Ubuntu 用 update-alternatives 管理多 JDK,先安装 openjdk-11-jdk-headless:
sudo apt-get install -y openjdk-11-jdk-headless
实测输出节选(实测首尾,dpkg 安装阶段后即完成 update-alternatives 登记):
update-alternatives: using /usr/lib/jvm/java-11-openjdk-amd64/bin/jjs to provide /usr/bin/jjs (jjs) in auto mode
update-alternatives: using /usr/lib/jvm/java-11-openjdk-amd64/bin/rmic to provide /usr/bin/rmic (rmic) in auto mode
查看系统已登记的 java 候选路径:
update-alternatives --list java
ls /usr/lib/jvm/
实测回显:
/usr/lib/jvm/java-11-openjdk-amd64/bin/java
/usr/lib/jvm/java-17-openjdk-amd64/bin/java
java-1.11.0-openjdk-amd64
java-1.17.0-openjdk-amd64
java-11-openjdk-amd64
java-17-openjdk-amd64
切版本最稳妥的方式是会话内显式设置 JAVA_HOME,不改全局默认。切到 11 验证:
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH
java -version
实测回显:
openjdk version "11.0.32.1" 2026-08-18
OpenJDK Runtime Environment (build 11.0.32.1+1-post-1ubuntu1-22.04-Ubuntu)
OpenJDK 64-Bit Server VM (build 11.0.32.1+1-post-1ubuntu1-22.04-Ubuntu, 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);
System.out.println("run under JDK 11: getCount(apple) = " + bag.getCount("apple"));
}
}
先切回 17 恢复环境再切 11 的操作相同(把 JAVA_HOME 换成 /usr/lib/jvm/java-17-openjdk-amd64 即可)。JDK 11 下的编译与运行:
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
实测回显:
run under JDK 11: getCount(apple) = 3
major version: 55
⚠️ 注意:用 JDK 17 编译出的 class(major 61)直接丢给 JDK 11 运行会报 UnsupportedClassVersionError(class file version 61.0 与 55.0 不匹配)。保证「编译 JDK 与运行 JDK 一致」,或像 5.1 的 pom 那样把 maven.compiler.source/target 压到 8,产物即可在 8/11/17 通用。
七、卸载与清理
按安装的逆序清理,每步都给验证命令。先删示例与下载物:
rm -rf /root/collections-lab /tmp/maven-demo
卸载演示用的 JDK 11(若生产需要 11 可跳过此步):
sudo apt-get remove --purge -y openjdk-11-jdk-headless openjdk-11-jre-headless
update-alternatives --list java
实测输出节选(实测首尾):
After this operation, 258 MB disk space will be freed.
/usr/lib/jvm/java-17-openjdk-amd64/bin/java
update-alternatives 只剩 17 一条,说明 11 已卸载干净。再卸 Maven:删软链与 /opt 安装目录,然后验证 mvn 不可用:
sudo rm -f /usr/local/bin/mvn
sudo rm -rf /opt/apache-maven-3.9.16
command -v mvn
实测回显(command -v 无输出且退出码非 0,bash 打印未找到提示):
mvn: not found
如需彻底移除 JDK 17(仅当本机不再需要任何 Java 环境):sudo apt-get remove --purge -y openjdk-17-jdk-headless,验证方式同上。~/.m2 是 Maven 本地仓库缓存,确认不再使用 Maven 后可一并删除。
八、常见问题 FAQ
Q1: 3.x 还能用吗?为什么文档总强调 4.x?3.x 的包名是 org.apache.commons.collections,4.x 改为 org.apache.commons.collections4(Maven 坐标也从 commons-collections 变为 org.apache.commons:commons-collections4),二者二进制不兼容。更重要的是安全史:3.x 的 InvokerTransformer 等 functors 类实现了 Serializable,在 Java 反序列化场景被 ysoserial 的 CommonsCollections 系列利用链反复利用(CVE-2015-6420 相关),3.2.2 虽做了部分修补但该系列已 EOL;4.1 起 functors 类不再实现 Serializable,从根源阻断了这类利用链(本篇 2.1 表中的 3.2.2 与 4.6.0 jar 可直接 javap 对比验证)。新项目必须用 4.x。
Q2: 编译 HashBag 示例时提示 deprecated 是怎么回事?4.6.0 起官方把 Bag/HashBag 标记为过时,推荐迁移到等价的 MultiSet/HashMultiSet(对应 4.6.0 RELEASE-NOTES 中 COLLECTIONS-893 的 MultiSet 能力补齐),计数语义与 getCount 用法完全一致。已有代码可继续用,新代码建议直接用 HashMultiSet。
Q3: 不装 Maven 可以用库吗?可以,5.2 的方案B就是:官方 bin 包 + javac/java -cp 直跑,零额外工具。只是失去依赖管理与构建生命周期,适合单文件验证与离线环境。
Q4: 运行报 UnsupportedClassVersionError 怎么办?这是编译用高版本 JDK、运行用低版本 JRE 导致的(如 17 编译、11 运行)。用 java -version 与 javac -version 双向核对当前会话版本,或按第六节用 JAVA_HOME 显式切换;跨版本交付时在 pom 固定 maven.compiler.source/target=8。
九、参考链接
- 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(Java 8+ 要求与 Bag 迁移说明):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