CentOS 8 安装 Apache Commons Math 指南

在 CentOS 8 上从零搭建 Apache Commons Math 3.6.1 使用环境,覆盖 JDK 8/17 并存切换、Maven 在线依赖与官方二进制包两套方案、JAVA_HOME 与 PATH 的实测差异、JDK 8 运行时兼容验证与常见问题排查,全部命令与回显均已实测。

Apache Commons MathApache Commons Math2026/10/15

CentOS 8 安装 Apache Commons Math 指南

目标:在 CentOS 8 上从零搭建 Apache Commons Math 3.6.1 的使用环境,完成 JDK 8/17 并存环境下的 JAVA_HOME 切换、Maven 在线依赖与官方二进制包两种引入方式、真实统计与线性代数运算验证。以下全部命令与回显均已在 CentOS 8(x86_64)实测通过。

一、环境信息

本节先固定本次实测所用软硬件基线,便于读者逐项对照复现。CentOS 8 的特点是系统默认 Java 为 1.8,与手动安装的 JDK 17 并存,本文将给出两者的切换与共存方法。

  • 操作系统:CentOS Linux release 8(x86_64)
  • 默认 Java:OpenJDK 1.8.0_312(java -version 实测,系统 dnf 仓库自带)
  • 备用 JDK:java-17-openjdk 17.0.1(/usr/lib/jvm/java-17-openjdk,包名 java-17-openjdk-17.0.1.0.12-2.el8_5.x86_64)
  • 构建工具:Apache Maven 3.5.4(Red Hat 构建版,系统仓库默认版本)
  • 目标库:Apache Commons Math 3.6.1(org.apache.commons:commons-math3:3.6.1)
  • 依赖来源:https://downloads.apache.org/commons/math/、https://repo1.maven.org/maven2/(网络直连可达)
  • Maven 示例工程目录:/opt/math-demo
  • 官方二进制包解压目录:/opt/math-jars

先确认系统版本与默认 Java、Maven 基线:

cat /etc/os-release | head -2
java -version 2>&1
mvn -v | head -3

输出:

NAME="CentOS Linux"
VERSION="8"
openjdk version "1.8.0_312"
OpenJDK Runtime Environment (build 1.8.0_312-b07)
OpenJDK 64-Bit Server VM (build 25.312-b07, mixed mode)
Apache Maven 3.5.4 (Red Hat 3.5.4-5)
Maven home: /usr/share/maven
Java version: 1.8.0_312, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.312.b07-2.el8_5.x86_64/jre

验证点:系统默认 java 为 1.8.0_312,且 Maven 默认也绑定 JDK 8。Commons Math 3.6.1 虽只需 Java 1.5+,但本文示例工程按 release 17 编译(更贴近新工程现实),因此需把 Maven 切到 JDK 17(见 4.2 节);只想"运行"已编译好的程序则 JDK 8 也能胜任(见 4.6 节实测)。

二、前置条件

在开始安装前,请确认以下条件满足,否则后续步骤会因权限或网络问题中断。

  1. root 权限或 sudo:安装 JDK、Maven 需要写入系统目录(/usr/lib/jvm、/usr/share/maven)。
  2. 网络可达:需要访问 downloads.apache.org(官方二进制包)与 repo1.maven.org(Maven 中央仓库)。
  3. 磁盘空间:官方二进制包 18,577,952 字节(约 18 MB),加上本地 Maven 仓库缓存建议预留 ≥ 300 MB。
  4. 注意多 JDK 并存:CentOS 8 同时存在 JDK 8 与 JDK 17 时,java 命令由 PATH 决定、Maven 由 JAVA_HOME 决定,两者互不影响(实测见 4.2 节与 9.1 节 Q1),务必分别确认。

验证网络连通性(该库的下载目录与 Maven 中央仓库各探测一次):

curl -sI https://downloads.apache.org/commons/math/ | head -1
curl -sI https://repo1.maven.org/maven2/org/apache/commons/commons-math3/ | head -1

输出:

HTTP/1.1 200 OK
HTTP/1.1 200 OK

⚠️ 注意:Commons Math 是纯类库(无独立进程),不会注册系统服务,"安装"的实质是把 jar 放进工程或 classpath。若内网无法直连上述域名,需按企业代理配置放行。下载大文件截断的代理处理见 5.2 节。

三、版本选型说明

Apache Commons Math 是 Apache 基金会的数学与统计计算库。安装前必须先弄清它的版本断代事实,避免版本选型失误。本节给出 Maven Central 与官方下载目录的实测版本清单。

3.1 版本现状:稳定线断代约 10 年,新一代长期停留 beta

查询 Maven Central 上 commons-math3 的全量版本元数据:

curl -s https://repo1.maven.org/maven2/org/apache/commons/commons-math3/maven-metadata.xml

输出:

<?xml version="1.0" encoding="UTF-8"?>
<metadata>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-math3</artifactId>
  <versioning>
    <latest>3.6.1</latest>
    <release>3.6.1</release>
    <versions>
      <version>3.0</version>
      <version>3.1</version>
      <version>3.1.1</version>
      <version>3.2</version>
      <version>3.3</version>
      <version>3.4</version>
      <version>3.4.1</version>
      <version>3.5</version>
      <version>3.6</version>
      <version>3.6.1</version>
    </versions>
    <lastUpdated>20160321125613</lastUpdated>
  </versioning>
</metadata>

关键结论:latest/release 均为 3.6.1,lastUpdated=20160321125613(2016-03-21),此后至今无任何新版本——稳定线已断代约 10 年(2016→2026),但 API 成熟、零传递依赖,仍是生产首选。

新一代 commons-math4 在 Maven Central 有 6 个模块(core / legacy / legacy-core / legacy-exception / neuralnet / transform),实测每个模块都只发布过 4.0-beta1(2022-12-19)一个版本。以 commons-math4-legacy 为例验证:

curl -s https://repo1.maven.org/maven2/org/apache/commons/commons-math4-legacy/maven-metadata.xml

输出:

<?xml version="1.0" encoding="UTF-8"?>
<metadata>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-math4-legacy</artifactId>
  <versioning>
    <latest>4.0-beta1</latest>
    <release>4.0-beta1</release>
    <versions>
      <version>4.0-beta1</version>
    </versions>
    <lastUpdated>20221219132611</lastUpdated>
  </versioning>
</metadata>

官方下载目录的在架发行版:

curl -s https://downloads.apache.org/commons/math/binaries/ | grep -E "tar.gz|zip</a>"

输出:

<a href="commons-math-2.2.tar.gz">commons-math-2.2.tar.gz</a>                   2013-03-03 21:07   10M
<a href="commons-math3-3.6.1-bin.tar.gz">commons-math3-3.6.1-bin.tar.gz</a>            2016-03-21 12:48   18M
<a href="commons-math3-3.6.1-bin.zip">commons-math3-3.6.1-bin.zip</a>               2016-03-21 12:48   21M
<a href="commons-math4-4.0-beta1-bin.tar.gz">commons-math4-4.0-beta1-bin.tar.gz</a>        2022-12-19 13:19   13M
<a href="commons-math4-4.0-beta1-bin.zip">commons-math4-4.0-beta1-bin.zip</a>           2022-12-19 13:19   14M

3.2 版本对照与选型

版本线最新版本发布日期Java 要求状态与建议
commons-math33.6.12016-03-21Java 1.5+(实测字节码 major=49)生产环境首选;断代约 10 年但 API 稳定、零传递依赖、JDK 8/17 实测可运行
commons-math44.0-beta12022-12-19Java 8+仅建议评估迁移时试用;beta 后停滞约 4 年,官方自述 "work-in-progress"

解读:新项目直接选 commons-math3 3.6.1。两者包名不同(org.apache.commons.math3 与 org.apache.commons.math4),可在同一 classpath 共存;CentOS 8 默认 JDK 8 也能直接运行 math3(major=49 字节码),只是编译新代码才需要 JDK 17。

💡 技术拓展:如果将来要从 math3 迁移到 math4,先看三张"地图"再动手——

迁移关注点math3 3.6.1 现状math4 4.0-beta1 去向说明
旧 API 主体(DescriptiveStatistics、TTest 等)org.apache.commons.math3.*org.apache.commons.math4.legacy.*(commons-math4-legacy 模块)官方 RELEASE-NOTES 明确:升级主要就是改顶层包名
核心工具(MathArrays、FastMath 等)org.apache.commons.math3.util.*org.apache.commons.math4.legacy.core.*(legacy-core 模块)FastMath 更名 AccurateMath,位于 org.apache.commons.math4.legacy.core.jdkmath
低层能力(随机数、数字类型、几何、统计)混在 math3 内已拆分到独立组件 Commons RNG / Numbers / Geometry / Statistics迁移时需按功能改引对应新组件,不再是"一个依赖全包"

迁移决策建议:math4 至今只有 beta 且停滞约 4 年,生产迁移收益有限;若确需迁移,保持 math3 与 math4 同 classpath 过渡(包名不同不冲突),按模块逐步替换,低层功能改引 RNG/Numbers/Geometry/Statistics。

四、在线安装方案(A:Maven 依赖引入)

官方推荐方式:通过 Maven 引入 commons-math3:3.6.1,由构建工具自动下载并管理 jar。适合可联网的开发/构建环境。

4.1 方案说明与适用场景

本方案先在 JDK 8/17 并存环境中把 Maven 切到 JDK 17,再创建一个最小 Maven 工程引入 commons-math3:3.6.1,编译运行一个真实统计程序完成验证,最后额外验证 JDK 8 运行时兼容性。适合持续集成、可访问中央仓库的场景。

4.2 切换 Maven 使用 JDK 17

如系统尚未安装 JDK 17 与 Maven,CentOS 8 可执行 dnf install -y java-17-openjdk java-17-openjdk-devel maven 安装;本文实测环境三者均已就绪,安装后以下述命令与回显为准。

CentOS 8 的系统 Maven 3.5.4 通过 JAVA_HOME 决定所用的 JDK。先设置并验证 JDK 17 可用:

export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
$JAVA_HOME/bin/java -version 2>&1

输出:

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)

关键事实(实测):设置 JAVA_HOME 不会改变 PATH 上的 java 命令——此时 java -version 仍是 1.8.0_312。mvn 认 JAVA_HOME,java 认 PATH,两者互不影响。持久化设置方法见第七章;排障见 9.1 节 Q1。

4.3 创建 Maven 工程并引入依赖

创建工程目录:

mkdir -p /opt/math-demo/src/main/java/demo

/opt/math-demo/pom.xml 全文:

<?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>demo</groupId>
  <artifactId>math-demo</artifactId>
  <version>1.0.0</version>
  <packaging>jar</packaging>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.release>17</maven.compiler.release>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-math3</artifactId>
      <version>3.6.1</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.11.0</version>
      </plugin>
    </plugins>
  </build>
</project>

逐项说明:

  • project.build.sourceEncoding=UTF-8:源码编码。示例代码含中文注释/字符串,必须显式声明,否则按平台默认编码编译会报 unmappable character。
  • maven.compiler.release=17:用 JDK 17 语义产出字节码(要求 4.2 节的 JAVA_HOME 已切到 17)。commons-math3 自身是 Java 5 字节码(major=49),可被任何更高版本 JDK 运行。
  • dependencies:仅声明 commons-math3:3.6.1 一项。该库零传递依赖,无需再补任何 jar。
  • maven-compiler-plugin 显式固定 3.11.0:Maven 3.5.4(Red Hat 构建版)同样默认绑定老版 compiler 插件,不认识 maven.compiler.release 属性,会退回 source/target=1.5 并被 JDK 17 拒绝。排障见 9.2 节 Q2。

4.4 编写最小验证程序

/opt/math-demo/src/main/java/MathCheck.java 全文:

import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;

public class MathCheck {
    public static void main(String[] args) {
        DescriptiveStatistics ds = new DescriptiveStatistics();
        for (double v : new double[] {9, 2, 5, 4, 12, 7, 8, 11, 9, 3}) {
            ds.addValue(v);
        }
        System.out.println("N=" + ds.getN()
            + " mean=" + ds.getMean()
            + " sd=" + ds.getStandardDeviation()
            + " p50=" + ds.getPercentile(50));
        System.out.println("commons-math3 OK");
    }
}

说明:用 commons-math3 的描述统计类 DescriptiveStatistics 对 10 个测量值计算样本数、均值、标准差与中位数,是库最核心的统计入口。

4.5 编译与运行验证

编译(mvn 读取 JAVA_HOME 使用 JDK 17):

export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
cd /opt/math-demo && mvn compile 2>&1 | tail -6

输出:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  22.618 s
[INFO] Finished at: 2026-10-14T15:28:36Z
[INFO] ------------------------------------------------------------------------

运行。注意必须用 $JAVA_HOME/bin/java 显式调用 JDK 17(PATH 上的 java 是 1.8,运行 major 61 的 class 会报错,排障见 9.1 节 Q1):

M3=/root/.m2/repository/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
$JAVA_HOME/bin/java -Dfile.encoding=UTF-8 -cp target/classes:$M3 MathCheck

输出:

N=10 mean=7.0 sd=3.39934634239519 p50=7.5
commons-math3 OK

验证点:均值 7.0(10 个数总和 70)、中位数 7.5(排序后第 5、6 个数 7 与 8 的平均),结果正确,说明依赖已正确引入且可运行。

4.6 JDK 8 运行时兼容验证

CentOS 8 生产环境大量存量应用仍跑在 JDK 8 上。commons-math3 3.6.1 本体是 Java 5 字节码(major=49),天然兼容;再把工程代码按 release 8 编译后,交由系统默认 JDK 8 运行时验证完整链路:

export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
cd /opt/math-demo
$JAVA_HOME/bin/javac --release 8 -encoding UTF-8 -cp ~/.m2/repository/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar -d classes8 src/main/java/demo/MathDemo.java
javap -v -cp classes8 demo.MathDemo 2>/dev/null | grep major
java -version 2>&1 | head -1
M3=/root/.m2/repository/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
java -Dfile.encoding=UTF-8 -cp classes8:$M3 demo.MathDemo ttest

输出:

  major version: 52
openjdk version "1.8.0_312"
== TTest(配对 t 检验 / 同方差 t 检验) ==
pairedT(before, after)       = -13.717203674463095
pairedTTest p 值(双侧)        = 2.5795569554518058E-6
homoscedasticT(before, after) = -1.596337345388562
homoscedasticTTest p 值(双侧) = 0.13273255836476072

逐项说明:--release 8 产出 major=52(Java 8)字节码;随后直接用 PATH 上的 java(1.8.0_312)运行,配对 t 检验完整执行成功。结论:math3 3.6.1 + JDK 8 运行时完全兼容,存量 JDK 8 应用可直接引入。

五、离线安装方案(B:官方二进制包)

适合内网隔离、无法访问中央仓库的环境。官方 commons-math3-3.6.1-bin.tar.gz 内含主 jar 与 javadoc/sources,且零传递依赖,解压即用,无需补任何第三方 jar。

5.1 方案说明与适用场景

本方案从官方下载目录获取二进制包,做哈希校验后解压,再用 javac/java -cp 直接编译运行验证。全程不依赖 Maven;JDK 用系统自带的 1.8 或 JDK 17 均可(math3 是 major=49 字节码)。

5.2 下载与校验

创建存放目录并下载(实测环境直连 downloads.apache.org 速度仅约 46KB/s 且大文件直连曾出现截断,因此走本地代理下载;无代理环境可去掉 -x 参数直连,下载后务必校验):

mkdir -p /opt/math-jars
cd /opt/math-jars
curl -sLO -x http://192.168.1.62:7897 https://downloads.apache.org/commons/math/binaries/commons-math3-3.6.1-bin.tar.gz
curl -sLO -x http://192.168.1.62:7897 https://downloads.apache.org/commons/math/binaries/commons-math3-3.6.1-bin.tar.gz.sha256

核对官方 sha256(官方只提供 sha1/sha256/asc,没有 sha512 校验文件):

ls -l commons-math3-3.6.1-bin.tar.gz
cat commons-math3-3.6.1-bin.tar.gz.sha256
sha256sum commons-math3-3.6.1-bin.tar.gz
gzip -t commons-math3-3.6.1-bin.tar.gz && echo "gzip OK"

输出:

-rw-r--r-- 1 root root 18577952 Oct 14 15:53 commons-math3-3.6.1-bin.tar.gz
7fc2750a5759b2cdb951ede83779f39c195705273ab010d42356ec676fe99674 *./math/binaries/commons-math3-3.6.1-bin.tar.gz
7fc2750a5759b2cdb951ede83779f39c195705273ab010d42356ec676fe99674  commons-math3-3.6.1-bin.tar.gz
gzip OK

验证点:包大小 18,577,952 字节,本机计算 sha256 与官方 .sha256 文件一致,gzip 完整性通过。直连截断的排障过程见 9.4 节 Q4。

5.3 解压与查看结构

解压并查看内容:

tar xzf commons-math3-3.6.1-bin.tar.gz
ls commons-math3-3.6.1/

输出:

LICENSE.txt
NOTICE.txt
RELEASE-NOTES.txt
commons-math3-3.6.1-javadoc.jar
commons-math3-3.6.1-sources.jar
commons-math3-3.6.1-test-sources.jar
commons-math3-3.6.1-tests.jar
commons-math3-3.6.1-tools.jar
commons-math3-3.6.1.jar
docs

主 jar 内含 1402 个条目(jar tf commons-math3-3.6.1.jar | wc -l 实测),顶层包为 org/apache/commons/math3/。用 javap 验证字节码版本:

javap -v -cp commons-math3-3.6.1/commons-math3-3.6.1.jar org.apache.commons.math3.stat.descriptive.DescriptiveStatistics 2>/dev/null | grep -E "major|minor" | head -2

输出:

  minor version: 0
  major version: 49

解读:major=49 即 Java 5 字节码,与 pom 声明的 maven.compiler.source/target=1.5 一致——系统自带的 JDK 8 也能直接加载运行。

5.4 手动编译运行验证

复用 4.4 节的 MathCheck.java,把源码放到 /opt/math-jars/check-src/,直接以官方 jar 作为 classpath 编译并运行:

cd /opt/math-jars
mkdir -p check-src check-classes
cp /opt/math-demo/src/main/java/MathCheck.java check-src/
javac -encoding UTF-8 -cp commons-math3-3.6.1/commons-math3-3.6.1.jar -d check-classes check-src/MathCheck.java
java -Dfile.encoding=UTF-8 -cp check-classes:commons-math3-3.6.1/commons-math3-3.6.1.jar MathCheck

输出:

N=10 mean=7.0 sd=3.39934634239519 p50=7.5
commons-math3 OK

验证点:结果与方案 A 完全一致。本步 javac/java 用的是系统默认 JDK 8(math3 为 major=49 字节码,JDK 8 编译运行均可),说明不依赖 Maven、不依赖 JDK 17、纯 jar 直跑同样可用。

六、方案对比与选择建议

两种方案各有取舍,本节汇总关键差异并给出选型建议。

维度方案 A:Maven 依赖方案 B:官方二进制包
是否需联网构建时需访问中央仓库仅下载阶段需联网(可离线分发)
安装方式声明依赖自动下载手动下载 + 校验 + 解压
依赖完整性自动解析(零传递依赖,只有 math3 一个 jar)零传递依赖,主 jar 解压即用
JDK 要求编译需 JDK 17(release 17 示例);仅运行可用 JDK 8编译运行均可用 JDK 8 或 17
附加产物仅主 jar附带 javadoc/sources/tests jar 与 docs 目录
适用场景CI/可联网开发内网隔离、离线运行、JDK 8 存量环境

选择建议:可联网的新工程选方案 A(配合 4.2 节 JAVA_HOME 切换);内网隔离或 JDK 8 存量环境选方案 B(一次校验下载后任意分发,JDK 8 即可编译运行)。两方案的 MathCheck 实测输出一致,可放心互换。

七、配置说明

Commons Math 是纯类库,没有任何配置文件。CentOS 8 上运行期需要关注的"配置"集中在 JAVA_HOME 与编码两件事,本节逐项说明实测要点。

JAVA_HOME 持久化:CentOS 8 的 Maven 由 JAVA_HOME 决定所用 JDK,写进 profile 脚本对所有登录会话生效:

echo "export JAVA_HOME=/usr/lib/jvm/java-17-openjdk" > /etc/profile.d/java17.sh
cat /etc/profile.d/java17.sh
. /etc/profile.d/java17.sh
mvn -v | head -3

输出:

export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
Apache Maven 3.5.4 (Red Hat 3.5.4-5)
Maven home: /usr/share/maven
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
java -version 2>&1 | head -1

输出:

openjdk version "1.8.0_312"

逐项解读:/etc/profile.d/java17.sh 让 Maven 在每个新登录会话中都使用 JDK 17;但 PATH 上的 java 命令仍由系统 alternatives 机制指向 1.8——这是 CentOS 8 的正常行为,不是配置失败。需要命令行 java 也指向 17 时,显式调用 $JAVA_HOME/bin/java,或用 dnf install java-17-openjdk-devel 后经 alternatives 调整系统默认(会影响全局,谨慎操作)。

其余配置要点:

  • 源码编码:javac 带 -encoding UTF-8,Maven 工程设 project.build.sourceEncoding=UTF-8(见 4.3 节)。
  • 运行时编码:locale 为 POSIX/C 时运行加 -Dfile.encoding=UTF-8,中文输出才不乱码(排障见 9.3 节 Q3)。
  • JVM 内存:库本身对内存无特殊要求,本文全部示例均以 JVM 默认参数运行;处理超大样本时按需自行追加 -Xms/-Xmx 启动参数。

八、升级、降级与多版本管理

本节说明版本变更的实际操作空间与 math3/math4 共存方法。

8.1 3.x 线内的版本变更

Maven Central 元数据显示 3.x 共 10 个版本(3.0 至 3.6.1,见 3.1 节)。Maven 方式改版本号即可,例如回退 3.5:

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-math3</artifactId>
  <version>3.5</version>
</dependency>

二进制包方式则从归档目录 https://archive.apache.org/dist/commons/math/binaries/ 下载对应版本包替换(该目录可回溯 commons-math 1.0(2004-12-07)以来全部历史版本)。3.x 各版本 API 高度兼容,通常无需改代码。

8.2 math3 与 math4 多版本共存

math3 与 math4 顶层包名不同(org.apache.commons.math3 与 org.apache.commons.math4),可在同一 classpath 共存,便于迁移期渐进替换。做法:把 math4 各模块 jar(commons-math4-core/legacy/legacy-core/legacy-exception,4.0-beta1)与 math3 jar 一起放入 -cp,代码里 math3 类正常 import,math4 类写全限定名(如 org.apache.commons.math4.legacy.stat.descriptive.DescriptiveStatistics)。共存验证的完整实测(源码、命令、逐行回显)见第 1 篇《Ubuntu 22.04 安装 Apache Commons Math 指南》8.2 节,两个平台的 JVM 行为一致,可直接照做。

8.3 jar 目录式多版本管理

离线场景可在 /opt/math-jars 下按版本建目录并存多套 jar(如 commons-math3-3.6.1/ 与 commons-math-4.0-beta1/),运行时用 -cp 显式指定所用目录中的 jar,互不干扰。

九、常见问题(FAQ)

Q1:export JAVA_HOME=/usr/lib/jvm/java-17-openjdk 后运行程序报 UnsupportedClassVersionError 怎么办?

完整实测现象(把 release 17 编译的 class 交给 PATH 上的 java 1.8 运行):

Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.UnsupportedClassVersionError: MathCheck 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 52.0
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:473)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:74)

(输出节选,堆栈其后还有十余行 at java.lang.ClassLoader.loadClass 等帧,最终 EXIT=1。)

定位:CentOS 8 上 export JAVA_HOME 只影响 mvn 等读取该变量的工具,不影响 PATH 上的 java 命令——java 仍由系统 alternatives 指向 1.8.0_312,而 class 文件版本 61.0(Java 17)无法在只识别 52.0(Java 8)的运行时上加载。解决:显式调用 JDK 17 的 java:

M3=/root/.m2/repository/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
$JAVA_HOME/bin/java -Dfile.encoding=UTF-8 -cp target/classes:$M3 MathCheck

输出:

N=10 mean=7.0 sd=3.39934634239519 p50=7.5
commons-math3 OK

另两条出路:按 4.6 节把工程字节码降到 --release 8 由 JDK 8 直接运行;或按第七章持久化 JAVA_HOME 并显式使用 $JAVA_HOME/bin/java。注意 commons-math3 自身是 major=49 字节码,此坑与库无关,是工程类与运行时版本不匹配所致。

Q2:mvn compile 报 Source option 5 is no longer supported. Use 7 or later. 怎么办?

完整现象(同时报 Target option 5 is no longer supported. Use 7 or later.):

[ERROR] Source option 5 is no longer supported. Use 7 or later.
[ERROR] Target option 5 is no longer supported. Use 7 or later.

定位:CentOS 8 的 Maven 3.5.4 同样默认绑定老版 maven-compiler-plugin(3.1),不认识 maven.compiler.release 属性,按 1.5 处理后被 JDK 17 的 javac 拒绝。解决:在 pom 的 <build><plugins> 中显式固定 maven-compiler-plugin 版本为 3.11.0(见 4.3 节 pom 全文)。修复后按 4.5 节实测 BUILD SUCCESS。

Q3:运行时中文输出变成 ??? 怎么办?

系统 locale 为 POSIX/C 时,JVM 默认输出编码是 ASCII,中文字符无法映射。实测对比:不加参数运行时中文变问号,数字结果不受影响。解决:运行时追加 JVM 系统属性 -Dfile.encoding=UTF-8(见 4.5 节运行命令),编译侧 javac 加 -encoding UTF-8、Maven 工程设 project.build.sourceEncoding=UTF-8。4.6 节 JDK 8 运行验证同样带该参数,中文分组标题与输出均正常。

Q4:直连 downloads.apache.org 下载的包解压报错怎么办?

实测现象:直连下载的 commons-math3-3.6.1-bin.tar.gz 只有 14,767,929 字节(完整应为 18,577,952),校验命令报错如下:

gzip: commons-math3-3.6.1-bin.tar.gz: unexpected end of file
tar: Unexpected EOF in archive

定位:大文件直连下载中途截断(实测直连速度仅约 46KB/s)。解决:走代理重新下载(见 5.2 节实测命令),重下后 18,577,952 字节、sha256 与官方一致、gzip -t 通过。教训:任何二进制包必须做哈希校验后再解压。

十、卸载与清理

Commons Math 不做系统级安装,删除 jar、工程与缓存即可完全清理:

rm -rf /opt/math-demo /opt/math-jars
rm -f /etc/profile.d/java17.sh
ls -d /opt/math-demo 2>/dev/null || echo "math-demo removed"

输出:

math-demo removed

Maven 方式还需清理本地仓库缓存中的 math3(或整库):

rm -rf ~/.m2/repository/org/apache/commons/commons-math3

如需同时移除 JDK 17 与 Maven(JDK 8 是系统默认组件,建议保留):

dnf remove -y java-17-openjdk java-17-openjdk-devel maven

⚠️ 注意:dnf remove 仅移除软件包;本文的示例程序与 jar 均在 /opt 与 ~/.m2,按上方命令清理即可,无残留系统服务或开机项。移除 JDK 17 前确认没有其他应用依赖 $JAVA_HOME。

十一、参考链接

  1. Apache Commons Math 官方站点:https://commons.apache.org/proper/commons-math/
  2. 官方发行下载目录:https://downloads.apache.org/commons/math/
  3. 历史版本归档目录:https://archive.apache.org/dist/commons/math/
  4. Maven 中央仓库坐标页:https://repo1.maven.org/maven2/org/apache/commons/commons-math3/
  5. Commons Math 3.6.1 Javadoc(二进制包内含 docs/ 离线版):https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/