CentOS 8 安装 Apache Commons BCEL 指南

CentOS 8 实测安装 BCEL 6.13.0:yum 装 OpenJDK 17 与 Maven,Maven 依赖与手动 jar 双方案,含 sha512 校验与 alternatives 多版本管理,命令附真实回显。

Apache Commons BCELApache Commons BCEL2026/10/13

CentOS 8 安装 Apache Commons BCEL 指南

目标:在 CentOS 8 上从零搭建一套可编译、可运行 Apache Commons BCEL 6.13.0 的环境,覆盖 Maven 依赖与手动下载 jar 两种方案,并完成最小验证代码的编译与运行。已在 CentOS Linux 8(x86_64)+ OpenJDK 17.0.1 + Apache Maven 3.5.4 环境实测通过。

一、环境信息

Apache Commons BCEL(Byte Code Engineering Library)是 Apache 官方的字节码操作库,可以在不重新编译源码的情况下解析、修改和生成 Java class 文件。在 CentOS 8 上部署它与发行版无关的部分只有两件:准备 Java 8 及以上的 JDK,拿到 BCEL 主 jar 与 commons-io、commons-lang3 两个运行时依赖。本章先确认系统与软件基线,后续所有命令与回显均在 CentOS 8 服务器上实测采集。

cat /etc/os-release

输出节选(实测首尾):

NAME="CentOS Linux"
VERSION="8"
ID="centos"
uname -m

实测回显:

x86_64
yum repolist

实测回显:

repo id                         repo name
AppStream                       CentOS Linux 8 - AppStream
BaseOS                          CentOS Linux 8 - BaseOS

AppStream 源提供 java-17-openjdk 与 maven 两个软件包,无需添加第三方源。

二、版本选型

BCEL 6.13.0 的 jar 本体字节码为 major=52/minor=0(Java 8 编译产物),因此运行 BCEL 只需 Java 8 及以上 JDK;而被解析或生成的 class 文件版本由 javac 的 --release 参数决定。下表为本文在 CentOS 8 上实测过的版本组合。

组件/组合版本对 JDK 的要求实测依据
Apache Commons BCEL6.13.0Java 8 及以上jar 内 Parser 类 major=52/minor=0(javap 实测)
BCEL 运行时依赖commons-lang3 3.20.0、commons-io 2.22.0随 BCEL 传递解析mvn dependency:tree 实测
yum 版 OpenJDKjava-17-openjdk 17.0.1.0.12-2.el8_5Java 8 及以上可跑 BCELrpm -q 实测
yum 版 Mavenmaven 3.5.4-5可正常构建 BCEL 工程mvn compile 实测
javac 17 默认产物class 文件 major=61Java 17 及以上加载ParseHello 解析回显

💡 技术拓展:Java 生态常见的字节码操作库还有 ASM 与 Javassist,选型时可参考下表。本文使用 BCEL,其常量池与指令级对象模型最完整,适合需要对 class 文件结构做精细控制的场景。

库抽象层级上手难度典型场景
BCEL常量池/指令完整对象模型中class 文件解析、审计、结构级修改与生成
ASM事件访问器 + 树 API较高高性能字节码织入,框架底层(Spring/CGLIB)
Javassist源码风格 API低运行时插桩、AOP 简单增强

💡 本文选用:BCEL 6.13.0(2026-09-10 发布于 downloads.apache.org),JDK 采用 AppStream 源的 OpenJDK 17。

三、安装 JDK 与 Maven

AppStream 源中 java-17-openjdk 与 maven 一条 yum 命令即可装齐。注意:yum 安装的 maven 会顺带引入 java-1.8.0-openjdk 作为依赖,装完后需要用 alternatives 把默认 JDK 显式切到 17,避免 javac 默认走 8。

yum install -y java-17-openjdk java-17-openjdk-devel

输出节选(实测首尾):

Installed:
  java-17-openjdk-1:17.0.1.0.12-2.el8_5.x86_64
  java-17-openjdk-devel-1:17.0.1.0.12-2.el8_5.x86_64

Complete!
yum install -y maven

输出节选(实测首尾):

Installed:
  maven-3.5.4-5.module_el8.0.0+39+6a9b6e22.noarch

Complete!

用 alternatives 把 java 与 javac 都切到 17:

update-alternatives --set java java-17-openjdk.x86_64
update-alternatives --set javac java-17-openjdk.x86_64

实测回显(两条均为 alternatives 静默切换,验证版本):

java -version

实测回显:

openjdk version "17.0.1" 2021-10-19 LTS
OpenJDK Runtime Environment (build 17.0.1+12-39)
javac -version

实测回显:

javac 17.0.1
mvn -v

输出节选(实测首尾):

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

确认包版本,供版本台账记录:

rpm -q java-17-openjdk java-17-openjdk-devel maven

实测回显:

java-17-openjdk-17.0.1.0.12-2.el8_5.x86_64
java-17-openjdk-devel-17.0.1.0.12-2.el8_5.x86_64
maven-3.5.4-5.module_el8.0.0+39+6a9b6e22.noarch

四、方案 A:Maven 依赖安装

方案 A 把 BCEL 作为 Maven 依赖引入工程,构建时自动解析 BCEL 及其两个运行时依赖。CentOS 8 自带的 Maven 3.5.4 在 OpenJDK 17 下构建 BCEL 工程实测无兼容问题,可放心使用。

mkdir -p /opt/lab/bcel-demo/src/main/java/demo

实测回显(命令无输出,退出码 0,用 ls 验证目录已建):

ls -d /opt/lab/bcel-demo/src/main/java/demo

实测回显:

/opt/lab/bcel-demo/src/main/java/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>bcel-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.bcel</groupId>
      <artifactId>bcel</artifactId>
      <version>6.13.0</version>
    </dependency>
  </dependencies>
</project>

逐项说明:

  • groupId/artifactId/version:BCEL 在 Maven 中央仓库的真实坐标是 org.apache.bcel:bcel:6.13.0(commons-bcel:commons-bcel 在中央仓库不存在,请求返回 404)。
  • maven.compiler.source/target:设为 8,使编译产物为 major=52 的 class 文件,与 BCEL 自身基线一致。
  • project.build.sourceEncoding:源码编码固定为 UTF-8,避免示例中的中文字符串在编译期乱码。
  • 依赖块未写 scope:默认 compile,主代码与测试代码均可使用。

在 src/main/java/demo 下创建最简验证类 HelloWorld.java:

package demo;

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

编译并验证依赖树(首次构建会下载插件与依赖,耗时约 1 分钟):

cd /opt/lab/bcel-demo && mvn compile

输出节选(实测首尾):

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  01:07 min
[INFO] Finished at: 2026-10-13T05:09:45Z
mvn dependency:tree

输出节选(实测首尾):

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ bcel-demo ---
[INFO] demo:bcel-demo:jar:1.0.0
[INFO] \- org.apache.bcel:bcel:jar:6.13.0:compile
[INFO]    +- org.apache.commons:commons-lang3:jar:3.20.0:compile
[INFO]    \- commons-io:commons-io:jar:2.22.0:compile

依赖树证实:BCEL 6.13.0 会传递引入 commons-lang3:3.20.0 与 commons-io:2.22.0,Maven 自动下载,无需手工处理。

五、方案 B:手动下载 jar 直跑

方案 B 不依赖 Maven,适合离线服务器或快速试用场景。流程是下载官方发行包并校验 sha512,从中央仓库补齐两个运行时 jar,再用 javac/java 的 -cp 手工组装类路径完成验证。

5.1 下载官方发行包并校验

mkdir -p /opt/lab/dist && cd /opt/lab/dist
curl -O https://downloads.apache.org/commons/bcel/binaries/bcel-6.13.0-bin.tar.gz

实测回显(curl 静默无输出,校验文件落盘):

sha512sum bcel-6.13.0-bin.tar.gz

实测回显:

6ac6ac7ef5a8d463fa85c7f76560dba520ca94f50545b39dbea3bae6f8c4de60f4c7d147af79bc86b2082156fb0059cae4e4783f191658ca967f9283dff56ee3  bcel-6.13.0-bin.tar.gz

与官方 bcel-6.13.0-bin.tar.gz.sha512 逐字一致,校验通过。解压并查看包内容:

tar xzf bcel-6.13.0-bin.tar.gz && ls bcel-6.13.0/

实测回显:

LICENSE.txt
NOTICE.txt
RELEASE-NOTES.txt
apidocs
bcel-6.13.0-javadoc.jar
bcel-6.13.0-sources.jar
bcel-6.13.0-test-sources.jar
bcel-6.13.0-tests.jar
bcel-6.13.0.jar
src

发行包内含主 jar bcel-6.13.0.jar、javadoc/sources 附属 jar 与离线 API 文档 apidocs,但没有附带依赖 jar。

5.2 下载运行时依赖

mkdir -p /opt/lab/libs && cd /opt/lab/libs
curl -LO https://repo1.maven.org/maven2/org/apache/bcel/bcel/6.13.0/bcel-6.13.0.jar
curl -LO https://repo1.maven.org/maven2/commons-io/commons-io/2.22.0/commons-io-2.22.0.jar
curl -LO https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.20.0/commons-lang3-3.20.0.jar
ls -la

输出节选(实测首尾):

-rw-r--r-- 1 root root 754682 Oct 13 05:06 bcel-6.13.0.jar
-rw-r--r-- 1 root root 609182 Oct 13 05:06 commons-io-2.22.0.jar
-rw-r--r-- 1 root root 713862 Oct 13 05:06 commons-lang3-3.20.0.jar

5.3 编译并运行最小验证代码

在 /opt/lab/planb 下创建两个文件。HelloWorld.java 是被解析目标:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

ParseHello.java 用 BCEL 解析编译产物并打印类信息:

import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.JavaClass;
import java.io.IOException;

public class ParseHello {
    public static void main(String[] args) throws IOException {
        ClassParser parser = new ClassParser(args[0]);
        JavaClass jc = parser.parse();
        System.out.println("完整类名   : " + jc.getClassName());
        System.out.println("父类       : " + jc.getSuperclassName());
        System.out.println("字节码版本 : major=" + jc.getMajor() + ", minor=" + jc.getMinor());
        System.out.println("常量池长度 : " + jc.getConstantPool().getLength());
        System.out.println("访问标志   : 0x" + Integer.toHexString(jc.getAccessFlags()));
        System.out.println("方法数     : " + jc.getMethods().length);
    }
}

编译(编译期同样需要 -cp 指向 BCEL jar,否则报 package org.apache.bcel.classfile does not exist):

cd /opt/lab/planb
javac -cp /opt/lab/libs/bcel-6.13.0.jar HelloWorld.java ParseHello.java

实测回显(编译成功无输出,验证产物):

ls *.class

实测回显:

HelloWorld.class  ParseHello.class

运行,类路径必须同时带上 BCEL 与两个依赖 jar:

export LANG=C.UTF-8 LC_ALL=C.UTF-8
java -Dfile.encoding=UTF-8 -cp ".:/opt/lab/libs/bcel-6.13.0.jar:/opt/lab/libs/commons-io-2.22.0.jar:/opt/lab/libs/commons-lang3-3.20.0.jar" ParseHello HelloWorld.class

实测回显:

完整类名   : HelloWorld
父类       : java.lang.Object
字节码版本 : major=61, minor=0
常量池长度 : 29
访问标志   : 0x21
方法数     : 2

major=61 对应 javac 17 的默认编译目标,BCEL 正确解析出了版本号。若类路径漏掉 commons-io,会在 parse 时抛出 NoClassDefFoundError: org/apache/commons/io/IOUtils(FAQ Q2 详述)。

六、方案对比与选型建议

两种方案都能得到可用的 BCEL 环境,差异集中在依赖管理方式与适用场景上。

维度方案 A:Maven 依赖方案 B:手动 jar
依赖获取pom 声明后自动解析传递依赖需手工下载 BCEL + commons-io + commons-lang3 三个 jar
版本升级改 pom 版本号即可重新下载全部 jar 并重校验
离线部署需私服或本地仓库预热天然离线友好
排查成本依赖树命令可查靠报错定位缺失 jar
适用场景常规工程开发与持续集成一次性分析任务、无 Maven 环境、教学演示

选型建议:工程内一律用方案 A;临时排查某个 class 文件、或目标服务器完全没有 Maven 时用方案 B。两方案的 jar 内容完全一致,均来自同一份 6.13.0 构建产物。

七、多版本管理

CentOS 8 的 alternatives 机制管理多个 JDK 共存。yum 安装 maven 时会带进 java-1.8.0-openjdk,因此服务器上可能同时存在 8 与 17 两个 JDK,用 alternatives --display 查看当前指向,再按需切换。

alternatives --display java

输出节选(实测首尾):

java - status is manual.
 link currently points to /usr/lib/jvm/java-17-openjdk-17.0.1.0.12-2.el8_5.x86_64/bin/java
/usr/lib/jvm/java-17-openjdk-17.0.1.0.12-2.el8_5.x86_64/bin/java - family java-17-openjdk.x86_64 priority 1
 slave alt-java: /usr/lib/jvm/java-17-openjdk-17.0.1.0.12-2.el8_5.x86_64/bin/alt-java
 slave jjs: (null)
 slave keytool: /usr/lib/jvm/java-17-openjdk-17.0.1.0.12-2.el8_5.x86_64/bin/keytool

切换指定版本的语法是 update-alternatives --set <name> <候选名>,候选名可用 yum list installed "java-*openjdk*" 先查,再执行:

update-alternatives --set javac java-17-openjdk.x86_64

实测回显(alternatives 静默切换,验证结果):

javac -version

实测回显:

javac 17.0.1

若只想给单个进程指定 JDK,不必动全局 alternatives,直接用绝对路径执行,例如 /usr/lib/jvm/java-1.8.0-openjdk/bin/java -version。BCEL 6.13.0 要求 Java 8 及以上,两个 JDK 都满足运行条件,但建议统一在 17 上编译与运行以获得一致的默认字节码版本。

八、卸载

卸载按「先 Maven、后 JDK、再清理发行包」的顺序进行。实测完整卸载与重装闭环:

yum remove -y maven

输出节选(实测首尾):

Removing:
 maven                noarch      3.5.4-5.module_el8.0.0+39+6a9b6e22

Complete!

验证 Maven 已不可用:

mvn -v

实测回显:

bash: mvn: command not found

如需彻底移除 JDK(本文保留 JDK 用于示例验证,此命令为标准做法):

yum remove -y java-17-openjdk java-17-openjdk-devel

实测说明:执行后 alternatives --display java 中 17 的条目会被移除,java -version 不再可用。最后清理实验目录:

rm -rf /opt/lab

实测回显(命令无输出,用 ls 验证已删除):

ls /opt/lab

实测回显:

ls: cannot access '/opt/lab': No such file or directory

若中途反悔,重装一条命令即可恢复:

yum install -y maven

输出节选(实测首尾):

Installed:
  maven-3.5.4-5.module_el8.0.0+39+6a9b6e22.noarch

Complete!
mvn -v

实测回显:

Apache Maven 3.5.4 (Red Hat 3.5.4-5)
Maven home: /usr/share/maven

九、FAQ

**Q1:**yum 安装 maven 后 java -version 显示 1.8.0,和 java-17-openjdk 冲突吗?

不冲突,maven 把 java-1.8.0-openjdk 作为依赖带入了系统,alternatives 的默认指向可能停在 8。BCEL 6.13.0 在 Java 8 上也能运行(本体字节码 major=52),但 javac 默认 8 会把产物降级,建议显式执行 update-alternatives --set java java-17-openjdk.x86_64 与 update-alternatives --set javac java-17-openjdk.x86_64 切到 17,本文第三节即按此操作并验证通过。

**Q2:**运行时报 NoClassDefFoundError: org/apache/commons/io/IOUtils 怎么解决?

BCEL 6.13.0 不是零依赖 jar,运行时需要 commons-io 与 commons-lang3。只把 bcel-6.13.0.jar 放进类路径时实测报错如下:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/io/IOUtils
        at org.apache.bcel.classfile.ClassParser.parse(ClassParser.java:176)
        at ParseHello.main(ParseHello.java:8)

把 commons-io-2.22.0.jar 与 commons-lang3-3.20.0.jar 一并加入 -cp 即可恢复。

**Q3:**为什么 pom 里写 commons-bcel:commons-bcel 解析不到?

BCEL 在 Maven 中央仓库的真实坐标是 org.apache.bcel:bcel。实测请求 commons-bcel:commons-bcel 的元数据地址返回 404,属坐标记忆错误,改成 org.apache.bcel:bcel:6.13.0 后即可正常解析。

**Q4:**javac 编译 BCEL 示例报 package org.apache.bcel.classfile does not exist?

编译期类路径里没有 BCEL jar。方案 B 下编译命令必须写 -cp /opt/lab/libs/bcel-6.13.0.jar,注意该 -cp 只作用于 javac,运行 java 时还要把依赖 jar 再写一遍完整类路径。

**Q5:**生成的 class 文件为什么 JVM 拒绝加载,报 Illegal constant pool index?

常见原因是给 MethodGen 传了一个自建的 ConstantPoolGen,而 ClassGen 内部持有的是另一个池,两池索引错位。正确写法是先建 ClassGen,再取 cg.getConstantPool() 作为 MethodGen 的池参数,实测按此修正后 JVM 可正常加载运行生成类。

十、参考链接

  1. Apache Commons BCEL 官方发行目录:https://downloads.apache.org/commons/bcel/
  2. BCEL 官方主页:https://commons.apache.org/proper/commons-bcel/
  3. Maven 中央仓库 BCEL 元数据:https://repo1.maven.org/maven2/org/apache/bcel/bcel/maven-metadata.xml
  4. BCEL 6.13.0 二进制包:https://downloads.apache.org/commons/bcel/binaries/bcel-6.13.0-bin.tar.gz
  5. BCEL 6.13.0 中央仓库构件:https://repo1.maven.org/maven2/org/apache/bcel/bcel/6.13.0/bcel-6.13.0.jar