CentOS 8 安装 Apache Commons Weaver 指南

在 CentOS 8(已 EOL)上安装 Apache Commons Weaver 2.0(JDK 8 构建期织入器),覆盖阿里云 centos-vault 8.5.2111 源配置、dnf 安装 java-1.8.0-openjdk-devel 与 Maven 3.5.4、显式 JAVA_HOME、Maven 插件与官方 bin 包两种织入方案及 JDK 17 兼容性实测结论,命令回显均实测通过。

Apache Commons WeaverApache Commons Weaver2026/10/15

CentOS 8 安装 Apache Commons Weaver 指南

目标:在已停止维护(EOL)的 CentOS 8 上从零搭建 Apache Commons Weaver 2.0 的使用环境(java-1.8.0-openjdk-devel + Maven 3.5.4),跑通 privilizer 织入提供者的最小验证工程,并给出官方 bin 包 + 手动 classpath 的离线方案;本文全部命令与回显均已在 CentOS 8 实测通过。

Apache Commons Weaver 是 Apache Commons 下的构建期字节码织入框架:扫描编译产物 class → 按注解改写字节码 → 写回。官方内置 privilizer(@Privileged 方法体重写为 AccessController.doPrivileged 特权块)与 normalizer(匿名类收敛)两个织入提供者。在 CentOS 8 上安装有两个前置难点必须先解决:一是 CentOS 8 已于 2021 年底 EOL,官方源 mirror.centos.org 已下线,必须切换到归档源;二是 2.0 的织入器只能在 JDK 8 上运行(实测 JDK 17 织入报 Unsupported class file major version 61),且 el8 的 Maven 对 JDK 的定位行为与 Ubuntu 不同,需要显式确认。本文按实测可跑通的方式组织全流程。

一、环境信息

本节先固定可复现的基线环境,后续所有命令均在此环境执行。

  • 操作系统:CentOS Linux 8(NAME="CentOS Linux",VERSION="8",归档源 8.5.2111)
  • 架构:x86_64
  • JDK:java-1.8.0-openjdk-devel 1.8.0.312.b07(el8 appstream 包,织入器实测必须运行在 JDK 8)
  • 构建工具:Apache Maven 3.5.4(el8 appstream module 包)
  • 组件版本:Apache Commons Weaver 2.0(2018-09-07 发布)
  • Maven 坐标:org.apache.commons:commons-weaver-processor:2.0、org.apache.commons:commons-weaver-privilizer:2.0、org.apache.commons:commons-weaver-privilizer-api:2.0、org.apache.commons:commons-weaver-maven-plugin:2.0
  • 官方下载目录:https://downloads.apache.org/commons/weaver/
  • 归档镜像:https://mirrors.aliyun.com/centos-vault/8.5.2111/
  • 验证用工作目录:/work/mini-demo(Maven 最小验证工程)

系统与架构确认(实时回显):

cat /etc/os-release | head -2
NAME="CentOS Linux"
VERSION="8"
uname -m
x86_64

💡 技术拓展:在 Java 生态里给已有 class 增加能力有三条路线,Weaver 属于构建期织入——

路线代表发生时机特点
构建期字节码织入Commons Weaver、AspectJ ajcjavac 编译之后、打包之前产物自包含,运行期零额外依赖
类加载期织入(LTW)AspectJ Weaver(-javaagent)JVM 加载 class 时不改构建流程,但需 agent 与 weaving classloader
运行期动态代理JDK Proxy / CGLIB程序运行时只能包装接口/可继承方法,无字节码改动

本文采用 Commons Weaver(构建期织入):织入在 mvn package 阶段完成,运行期 classpath 干净(实测织入产物运行无需携带任何 Weaver jar)。

二、前置条件

本节说明安装前必须满足的条件。

  1. 具有 root 权限的 CentOS 8 系统。
  2. 可访问归档镜像源 mirrors.aliyun.com/centos-vault/(CentOS 8 EOL 后官方源已 404,见第三章 3.2 节)。
  3. 可访问 Maven 中央仓库 repo1.maven.org 与 Apache 官方下载站 downloads.apache.org(本文实测网络直连可达)。
  4. 至少 1 GB 可用磁盘空间。

网络连通性确认(实时回显):

curl -sI --max-time 20 https://repo1.maven.org/maven2/org/apache/commons/commons-weaver-processor/2.0/ | head -1
HTTP/1.1 200 OK
curl -sI --max-time 20 https://downloads.apache.org/commons/weaver/ | head -1
HTTP/1.1 200 OK

三、版本选型说明

本节回答「装哪个版本、用哪个 JDK、el8 源怎么配」。

3.1 Weaver 版本与模块清单

Commons Weaver 是低频发布项目:官方下载目录 https://downloads.apache.org/commons/weaver/ 上只有 2.0 一个版本线,binaries/ 目录实测只有 commons-weaver-2.0-bin.tar.gz 与 commons-weaver-2.0-bin.zip 两个二进制包(附 .sha256/.sha512/.asc)。RELEASE-NOTES.txt(2018-09-07)写明 "Requires Java 8 or greater",本版核心变更为 Java 8 基线(WEAVER-19)、xbean-finder 4.9(WEAVER-21)、ASM 6.2.1(WEAVER-22)、commons-parent v47(WEAVER-26)。2.0 之后无新版本发布,维护停滞,选型时需如实评估。

模块(中央仓库实测存在)作用是否必须
commons-weaver-processor:2.0织入处理器内核:扫描 class、按 SPI 加载提供者必须
commons-weaver-privilizer-api:2.0privilizer 注解(@Privileged/@Privilizing)privilizer 场景必须
commons-weaver-privilizer:2.0privilizer 织入提供者(重写特权块)privilizer 场景必须
commons-weaver-normalizer:2.0normalizer 织入提供者(收敛匿名类)可选
commons-weaver-maven-plugin:2.0Maven 插件(weave/prepare 等 goal)Maven 方案必须
commons-weaver-antlib:2.0Ant 任务可选

⚠️ 注意:部分资料提到的 commons-weaver-proxy「动态代理织入提供者」在 2.0 发布物与 Maven 中央仓库中均不存在(https://repo1.maven.org/maven2/org/apache/commons/commons-weaver-proxy/2.0/ 返回 404,bin 包内亦无此 jar),不要按该名称引用。

JDK 兼容性实测结论:执行织入的构建环境必须用 JDK 8。织入器运行在 JDK 17 时 weave 报错(实测回显):

[ERROR] Failed to execute goal org.apache.commons:commons-weaver-maven-plugin:2.0:weave (default) on project privilizer-demo: weaving failed due to java.lang.IllegalStateException: java.lang.IllegalArgumentException: Unsupported class file major version 61 -> [Help 1]

根因:privilizer 织入时要读取被调用方类文件(含 JDK 自身的 java/lang/System 等)判断可访问性,内嵌的 ASM 6.2.1(shaded 打包在 privilizer jar 内,无法替换)不支持 JDK 17 的 major 61 字节码。产物字节码为 major 52,可运行于任意更高版本 JRE;但 privilizer 的安全语义依赖 SecurityManager(JDK 17 起已废弃,参考 JEP 411),长期使用请评估迁移。

3.2 CentOS 8 EOL 与归档源配置

CentOS 8 EOL 后官方 mirror.centos.org 已下线,dnf makecache 会直接报 Failed to download metadata for repo 'appstream'。必须把仓库指向归档源;阿里云镜像实测可用(8.5.2111 是 AppStream 里同时有 java-1.8.0-openjdk-devel 与 maven 的稳定版本线)。覆盖仓库配置:

rm -f /etc/yum.repos.d/CentOS-*.repo
cat > /etc/yum.repos.d/vault.repo <<'EOF'
[baseos-vault]
name=CentOS-8.5.2111 - BaseOS
baseurl=https://mirrors.aliyun.com/centos-vault/8.5.2111/BaseOS/x86_64/os/
gpgcheck=0
enabled=1
[appstream-vault]
name=CentOS-8.5.2111 - AppStream
baseurl=https://mirrors.aliyun.com/centos-vault/8.5.2111/AppStream/x86_64/os/
gpgcheck=0
enabled=1
EOF
dnf clean all && dnf makecache 2>&1 | tail -2
# 输出节选(实测首尾)
CentOS-8.5.2111 - BaseOS                1.4 MB/s | 4.6 MB     00:03
CentOS-8.5.2111 - AppStream             991 kB/s | 8.4 MB     00:08
Metadata cache created.

验证点:Metadata cache created. 表示归档源元数据拉取成功;若此处报 403/404,检查 baseurl 中的 8.5.2111 是否拼写正确(阿里云 vault 目录按完整版本号组织,如 8.5.2111,不存在裸 8/ 目录)。

四、方案 A:Maven 依赖安装(在线,推荐)

本节通过 dnf 安装 JDK 8 与 Maven,再用 Maven 坐标引入 Weaver 模块并跑通 privilizer 织入最小验证工程。

4.1 方案说明

方案 A 的链路是:dnf 安装 java-1.8.0-openjdk-devel 与 maven → 显式导出 JAVA_HOME 指向 JDK 8 → 工程 pom.xml 声明 commons-weaver-privilizer-api(编译期注解)与 commons-weaver-maven-plugin(插件级依赖带入 privilizer 织入器)→ mvn package 在 process-classes 阶段自动织入 → 运行验证。

4.2 安装 JDK 8 与 Maven

dnf install -y java-1.8.0-openjdk-devel maven 2>&1 | tail -2
# 输出节选(实测首尾)
  xorg-x11-fonts-Type1-7.5-19.el8.noarch
Complete!

确认安装的精确版本:

dnf list installed java-1.8.0-openjdk-devel maven 2>/dev/null | tail -2
java-1.8.0-openjdk-devel.x86_64    1:1.8.0.312.b07-2.el8_5    @appstream-vault
maven.noarch                       1:3.5.4-5.module_el8.0.0+39+6a9b6e22    @appstream-vault

验证点:java-1.8.0-openjdk-devel 来自 @appstream-vault(即第三章配置的归档源),版本 1.8.0.312.b07;maven 为 3.5.4。

4.3 显式设置 JAVA_HOME 并确认 Maven 绑定

el8 的 Maven 启动脚本对 JDK 的定位不总是跟随系统默认 java(本机只装了 JDK 8 时它恰好选中了 8,但机器上有多套 JDK 时会选中错误版本且不报错),建议始终显式导出 JAVA_HOME:

echo "JAVA_HOME=$JAVA_HOME"
JAVA_HOME=
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk
mvn -v | head -3
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 version 显示 1.8.0_312 且 runtime 路径指向 java-1.8.0-openjdk。建议把 export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk 写入 /etc/profile.d/java8.sh 持久化。同时确认 javac 可用(JDK 而非 JRE):

javac -version
javac 1.8.0_312

4.4 创建最小验证工程

创建工程目录:

mkdir -p /work/mini-demo/src/main/java/demo

/work/mini-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>weaver-mini</artifactId>
  <version>1.0.0</version>
  <packaging>jar</packaging>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-weaver-privilizer-api</artifactId>
      <version>2.0</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.11.0</version>
      </plugin>
      <plugin>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-weaver-maven-plugin</artifactId>
        <version>2.0</version>
        <dependencies>
          <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-weaver-privilizer</artifactId>
            <version>2.0</version>
          </dependency>
        </dependencies>
        <configuration>
          <weaverConfig>
            <privilizer.policy>ALWAYS</privilizer.policy>
            <privilizer.accessLevel>public</privilizer.accessLevel>
          </weaverConfig>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>weave</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

逐项说明关键配置:

  • commons-weaver-privilizer-api:2.0:编译期注解来源(@Privileged)。
  • 插件级 <dependencies> 中的 commons-weaver-privilizer:2.0:织入提供者必须挂在 commons-weaver-maven-plugin 的 <dependencies> 下。插件经 ServiceLoader 从插件自身的类加载空间发现织入提供者;写成普通工程依赖时 weave goal 会静默空转(实测复现,见 FAQ Q2)。
  • weaverConfig:privilizer.policy=ALWAYS 织入为无条件 doPrivileged 块;privilizer.accessLevel=public 允许 @Privileged 标注 public 方法(默认 private,否则报错,见 FAQ Q3)。
  • el8 Maven 是 3.5.4,显式固定 maven-compiler-plugin:3.11.0 以避免 3.5.4 默认老版本编译插件对 source/target 属性支持不全的问题。

4.5 最小验证代码

/work/mini-demo/src/main/java/demo/SecretStore.java(特权方法提供者):

package demo;

import org.apache.commons.weaver.privilizer.Privileged;

/**
 * 特权方法提供者:readToken 的方法体需要以特权方式读取系统属性。
 */
public final class SecretStore {

    private SecretStore() {
    }

    @Privileged
    public static String readToken() {
        return System.getProperty("demo.token", "unset");
    }
}

/work/mini-demo/src/main/java/demo/ConfigClient.java(普通调用方):

package demo;

/**
 * 普通调用方:直接调用特权方法,自身不做任何声明。
 */
public final class ConfigClient {

    private ConfigClient() {
    }

    public static String token() {
        return SecretStore.readToken();
    }
}

/work/mini-demo/src/main/java/demo/Main.java(入口):

package demo;

public final class Main {

    private Main() {
    }

    public static void main(String[] args) {
        System.out.println("ConfigClient.token()   = " + ConfigClient.token());
        System.out.println("SecurityManager active = " + (System.getSecurityManager() != null));
    }
}

4.6 构建织入与运行验证

cd /work/mini-demo && mvn -B clean package 2>&1 | grep -E 'weave|security leak|BUILD|Total time'
[INFO] --- commons-weaver:2.0:weave (default) @ weaver-mini ---
[WARNING] Possible security leak: granting privileges to public method demo/SecretStore.readToken()Ljava/lang/String;
[INFO] BUILD SUCCESS
[INFO] Total time: 1.386 s

回显解读:weave (default) 在 process-classes 阶段执行织入;Possible security leak 是 privilizer 的访问级别审计提示(把特权授予 public 方法等于所有能调用者都获得特权),属预期警告而非错误。

运行织入后的程序:

java -Ddemo.token=secret-123 -cp target/classes demo.Main
ConfigClient.token()   = secret-123
SecurityManager active = false

用 javap 验证织入真实发生:

javap -p -c target/classes/demo/SecretStore.class | grep -E 'readToken_ACTION|doPrivileged|__privileged'
       0: new           #34                 // class demo/SecretStore$readToken_ACTION
       4: invokespecial #36                 // Method demo/SecretStore$readToken_ACTION."<init>":()V
       7: invokestatic  #42                 // Method java/security/AccessController.doPrivileged:(Ljava/security/PrivilegedAction;)Ljava/lang/Object;
  static java.lang.String __privileged_access$0();
       0: invokestatic  #48                 // Method __privileged_readToken:()Ljava/lang/String;
  private static java.lang.String __privileged_readToken();

结果解读:原方法体被搬进合成方法 __privileged_readToken(),readToken() 被改写为「构造特权动作 → AccessController.doPrivileged 执行 → 强转返回」,且运行期 classpath 只有 target/classes,无需任何 Weaver jar。

五、方案 B:官方 bin 包 + 手动 classpath 直跑(离线友好)

本节面向没有 Maven 的场景:下载官方 bin 包,用 javac/java 手动拼 classpath 完成编译、织入、运行。

5.1 方案说明

链路:下载校验 bin 包 → 解压得到 6 个模块 jar → 从中央仓库补齐 3 个传递依赖 jar → javac 编译 → 用 20 行 WeaveRunner 直调 WeaveProcessor.weave() → java 运行。

5.2 下载与完整性校验

mkdir -p /work/planb && cd /work/planb
curl -sO --max-time 120 https://downloads.apache.org/commons/weaver/binaries/commons-weaver-2.0-bin.zip
curl -sO --max-time 60 https://downloads.apache.org/commons/weaver/binaries/commons-weaver-2.0-bin.zip.sha256
ls -l commons-weaver-2.0-bin.zip
cat commons-weaver-2.0-bin.zip.sha256
sha256sum commons-weaver-2.0-bin.zip
-rw-r--r-- 1 root root 2146159 Oct 15 03:02 commons-weaver-2.0-bin.zip
f5ec5a73d8b3a43b44b31e3e0eea9249d444214579dd649b03ad171b527603f2
f5ec5a73d8b3a43b44b31e3e0eea9249d444214579dd649b03ad171b527603f2  commons-weaver-2.0-bin.zip

验证点:期望值与实测值逐字一致;不一致必须删除重下。

5.3 解包与补齐传递依赖

cd /work/planb && unzip -q -o commons-weaver-2.0-bin.zip && ls commons-weaver-2.0/
LICENSE-asm6.2.1.txt
LICENSE.txt
NOTICE.txt
RELEASE-NOTES.txt
commons-weaver-antlib-2.0.jar
commons-weaver-maven-plugin-2.0.jar
commons-weaver-privilizer-2.0.jar
commons-weaver-privilizer-api-2.0.jar
commons-weaver-processor-2.0.jar
commons-weaver-normalizer-2.0.jar

bin 包只含 Weaver 自身模块,命令行直跑还需 3 个传递依赖 jar(注解扫描与工具库),实测下载:

cd /work/planb
M=https://repo1.maven.org/maven2
curl -sO --max-time 60 $M/org/apache/xbean/xbean-finder-shaded/4.9/xbean-finder-shaded-4.9.jar
curl -sO --max-time 60 $M/org/apache/xbean/xbean-asm6-shaded/4.9/xbean-asm6-shaded-4.9.jar
curl -sO --max-time 60 $M/org/apache/commons/commons-lang3/3.7/commons-lang3-3.7.jar

5.4 编写织入入口并编译演示源码

/work/planb/WeaveRunner.java(完整内容):

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.commons.weaver.WeaveProcessor;

public class WeaveRunner {

    public static void main(String[] args) throws Exception {
        final String target = args[0];
        final List<String> classpath = new ArrayList<>(java.util.Arrays.asList(args[1].split(":")));
        final Properties config = new Properties();
        config.setProperty("privilizer.policy", "ALWAYS");
        config.setProperty("privilizer.accessLevel", "public");
        new WeaveProcessor(classpath, new File(target), config).weave();
        System.out.println("WEAVE_DONE");
    }
}

准备演示源码(复制 4.5 节三个类到 /work/planb/src/demo/),编译并织入:

cd /work/planb && mkdir -p classes
R=commons-weaver-2.0
javac -encoding UTF-8 -cp $R/commons-weaver-privilizer-api-2.0.jar -d classes src/demo/*.java
javac -encoding UTF-8 -cp $R/commons-weaver-processor-2.0.jar:$R/commons-weaver-privilizer-2.0.jar -d classes WeaveRunner.java
WC=$R/commons-weaver-processor-2.0.jar:$R/commons-weaver-privilizer-2.0.jar:$R/commons-weaver-privilizer-api-2.0.jar:xbean-finder-shaded-4.9.jar:xbean-asm6-shaded-4.9.jar:commons-lang3-3.7.jar
java -cp classes:$WC WeaveRunner /work/planb/classes $WC 2>&1 | grep -E 'PROVIDER|WARNING|WEAVE_DONE' | head -3
PROVIDER: org.apache.commons.weaver.privilizer.PrivilizerWeaver
WARNING: Possible security leak: granting privileges to public method demo/SecretStore.readToken()Ljava/lang/String;
WEAVE_DONE

回显解读:PROVIDER 说明 ServiceLoader 从 classpath 发现了 privilizer 织入提供者(bin 包 jar 内 META-INF/services/org.apache.commons.weaver.spi.Weaver 注册文件生效);WEAVE_DONE 表示织入完成。

⚠️ 注意:javac 必须带 -encoding UTF-8,否则 POSIX locale 下中文注释会报 unmappable character for encoding ASCII(实测 69 errors)。

5.5 运行织入产物

java -Ddemo.token=secret-123 -cp /work/planb/classes demo.Main
ConfigClient.token()   = secret-123
SecurityManager active = false

验证点:与方案 A 结果一致,产物等价,且运行期 classpath 无任何 Weaver jar。

六、方案对比与选择建议

维度方案 A:Maven 插件方案 B:bin 包 + 手动 classpath
织入触发process-classes 阶段自动执行自行调用 WeaveProcessor.weave()
依赖管理Maven 自动解析(含传递依赖)手工收集 3 个传递依赖 jar
与构建集成无缝,mvn package 一步到位需自写脚本拼 classpath
离线可用性首次需联网下载依赖下载完成后完全离线
适用场景常规工程开发(推荐)无构建体系环境、脚本化定制织入

选型建议:有构建体系一律选方案 A;把织入嵌入自研打包流水线时选方案 B。两方案可共存——CI 上用方案 A 出包,本地离线排查用方案 B。

七、配置说明

Weaver 没有独立配置文件,全部配置通过 Maven 插件的 weaverConfig(Properties 键值对)或 WeaveProcessor 构造参数传入。实测有效的配置键:

配置键取值说明
privilizer.policyNEVER / ON_INIT / DYNAMIC(默认) / ALWAYSALWAYS 织入为无条件 doPrivileged;DYNAMIC 每次 @Privileged 方法执行时检查 SecurityManager 再决定;ON_INIT 只在初始化时检查一次;NEVER 关闭织入
privilizer.accessLevelpublic / protected / package / private(默认)允许 @Privileged 标注的最大访问级别,超出即报错
privilizer.verifytrue / false织入后是否用 ASM 的 CheckClassAdapter 校验产物字节码(取自模块源码,本文未单独实测该开关)
normalizer.targetPackage合法包名normalizer 把合格匿名类重映射到该包下的 $normalized<摘要> 规范位置

环境变量方面,CentOS 8 上本文实测显式导出 JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk 是最稳妥做法(多 JDK 机器上 el8 Maven 不保证选对);持久化方式:

echo 'export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk' > /etc/profile.d/java8.sh
source /etc/profile.d/java8.sh && echo "JAVA_HOME=$JAVA_HOME"
JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk

八、常见问题(FAQ)

Q1:dnf makecache 报 Failed to download metadata for repo 'appstream'? CentOS 8 EOL 后官方源已下线,mirror.centos.org 无法解析或 404。解法:按第三章 3.2 节把仓库换成阿里云归档源(BaseOS 完整地址为 https://mirrors.aliyun.com/centos-vault/8.5.2111/BaseOS/x86_64/os/)。同网络环境下若 vault 源 403,多为基础镜像目录配置错误(el8 无裸 8/ 归档目录),核对完整版本号 8.5.2111。

Q2:mvn package 显示 BUILD SUCCESS 但 javap 发现类根本没被织入? 最常见原因:把 commons-weaver-privilizer 写成了普通工程依赖。插件经 ServiceLoader 从插件自身的类加载空间发现织入提供者,工程依赖进入不了该空间,weave goal 静默空转。解法:把该依赖挪到插件级 <dependencies>(见 4.4 节 pom),重跑 mvn clean package。

Q3:报 must have maximum access level 'private' but is defined wider ('public')? @Privileged 默认只允许标注 private 方法。解法:weaverConfig 增加 <privilizer.accessLevel>public</privilizer.accessLevel>。放宽后织入输出 Possible security leak 警告,属预期提示,评估接受即可。

Q4:织入时报 Unsupported class file major version 61? 在 JDK 17(或 11)上执行织入的典型报错:内嵌 ASM 6.2.1 只支持 major 52。解法:把构建环境换成 java-1.8.0-openjdk-devel 并显式 JAVA_HOME 指向 JDK 8(见 4.3 节),mvn -v 确认后重跑。产物字节码 major 52 可被更高版本 JRE 运行,但 privilizer 的安全语义依赖 SecurityManager(JDK 17 起废弃),长期规划参考 JEP 411。

Q5:Maven 3.5.4 太旧,插件会不兼容吗? 不会。commons-weaver-maven-plugin:2.0 对 Maven 版本要求很低,3.5.4 实测构建织入全部通过;唯一需要注意的是 3.5.4 默认绑定的编译插件较老,本文已在 pom 中显式固定 maven-compiler-plugin:3.11.0。

Q6:可以用 -javaagent 在运行期织入吗? 不可以。Commons Weaver 2.0 只提供构建期织入,官方发布物中没有 Java agent jar。需要类加载期织入请评估 AspectJ LTW 等方案(对比见第一章技术拓展表)。

九、卸载与清理

移除验证工程与下载产物:

rm -rf /work/mini-demo /work/planb
ls /work/mini-demo 2>&1
ls: cannot access '/work/mini-demo': No such file or directory

清理 Maven 本地仓库中的 Weaver 模块(影响所有工程,慎用):

rm -rf $HOME/.m2/repository/org/apache/commons/commons-weaver-*

卸载 JDK 8 与 Maven(先 -s 预演确认再真删):

dnf -s remove java-1.8.0-openjdk-devel maven 2>&1 | grep -cE 'Removing|Erasing'
2

确认无误后真正卸载:

dnf remove -y java-1.8.0-openjdk-devel maven && dnf autoremove -y

十、参考链接

  1. Apache Commons Weaver 官方主页:https://commons.apache.org/proper/commons-weaver/
  2. Apache Commons Weaver 官方下载目录:https://downloads.apache.org/commons/weaver/
  3. Commons Weaver 2.0 发布说明:https://downloads.apache.org/commons/weaver/RELEASE-NOTES.txt
  4. Maven 中央仓库坐标页:https://repo1.maven.org/maven2/org/apache/commons/commons-weaver-processor/
  5. Weaver Maven 插件文档:https://commons.apache.org/proper/commons-weaver/commons-weaver-maven-plugin/
  6. CentOS Vault 归档(阿里云镜像):https://mirrors.aliyun.com/centos-vault/