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 兼容性实测结论,命令回显均实测通过。
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 ajc javac编译之后、打包之前产物自包含,运行期零额外依赖 类加载期织入(LTW) AspectJ Weaver(-javaagent) JVM 加载 class 时 不改构建流程,但需 agent 与 weaving classloader 运行期动态代理 JDK Proxy / CGLIB 程序运行时 只能包装接口/可继承方法,无字节码改动 本文采用 Commons Weaver(构建期织入):织入在
mvn package阶段完成,运行期 classpath 干净(实测织入产物运行无需携带任何 Weaver jar)。
二、前置条件
本节说明安装前必须满足的条件。
- 具有 root 权限的 CentOS 8 系统。
- 可访问归档镜像源
mirrors.aliyun.com/centos-vault/(CentOS 8 EOL 后官方源已 404,见第三章 3.2 节)。 - 可访问 Maven 中央仓库
repo1.maven.org与 Apache 官方下载站downloads.apache.org(本文实测网络直连可达)。 - 至少 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.0 | privilizer 注解(@Privileged/@Privilizing) | privilizer 场景必须 |
commons-weaver-privilizer:2.0 | privilizer 织入提供者(重写特权块) | privilizer 场景必须 |
commons-weaver-normalizer:2.0 | normalizer 织入提供者(收敛匿名类) | 可选 |
commons-weaver-maven-plugin:2.0 | Maven 插件(weave/prepare 等 goal) | Maven 方案必须 |
commons-weaver-antlib:2.0 | Ant 任务 | 可选 |
⚠️ 注意:部分资料提到的
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 从插件自身的类加载空间发现织入提供者;写成普通工程依赖时weavegoal 会静默空转(实测复现,见 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.policy | NEVER / ON_INIT / DYNAMIC(默认) / ALWAYS | ALWAYS 织入为无条件 doPrivileged;DYNAMIC 每次 @Privileged 方法执行时检查 SecurityManager 再决定;ON_INIT 只在初始化时检查一次;NEVER 关闭织入 |
privilizer.accessLevel | public / protected / package / private(默认) | 允许 @Privileged 标注的最大访问级别,超出即报错 |
privilizer.verify | true / 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
十、参考链接
- Apache Commons Weaver 官方主页:https://commons.apache.org/proper/commons-weaver/
- Apache Commons Weaver 官方下载目录:https://downloads.apache.org/commons/weaver/
- Commons Weaver 2.0 发布说明:https://downloads.apache.org/commons/weaver/RELEASE-NOTES.txt
- Maven 中央仓库坐标页:https://repo1.maven.org/maven2/org/apache/commons/commons-weaver-processor/
- Weaver Maven 插件文档:https://commons.apache.org/proper/commons-weaver/commons-weaver-maven-plugin/
- CentOS Vault 归档(阿里云镜像):https://mirrors.aliyun.com/centos-vault/