You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用ASM将类的protected、包私有字段修改为public

字节码修改实现方案

你可以通过ASM字节码操作框架完成成员访问权限的修改,完整实现逻辑如下:

1. 核心修改逻辑

你需要遍历目标类的所有字段、方法,将非private的访问修饰符(protected、包私有)替换为public,访问修饰符的判断基于字节码中的访问标志位实现。

首先自定义字节码访问器:

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class AccessRepairVisitor extends ClassVisitor {
    public AccessRepairVisitor(ClassVisitor classVisitor) {
        // ASM版本根据你兼容的JDK版本选择,ASM9支持到JDK17+
        super(Opcodes.ASM9, classVisitor);
    }

    // 修改字段访问权限
    @Override
    public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
        // 排除private成员,将其余所有成员改为public
        if ((access & Opcodes.ACC_PRIVATE) == 0) {
            access = Opcodes.ACC_PUBLIC;
        }
        return super.visitField(access, name, descriptor, signature, value);
    }

    // 修改方法访问权限
    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        // 构造方法、普通方法统一处理,排除private成员
        if ((access & Opcodes.ACC_PRIVATE) == 0) {
            access = Opcodes.ACC_PUBLIC;
        }
        return super.visitMethod(access, name, descriptor, signature, exceptions);
    }
}

2. 补全loadClass方法

将修改后的字节码通过defineClass方法加载为Class对象即可:

@Override
public Class<?> loadClass(String className)
        throws ClassNotFoundException
{
    if (! this.needsAccessRepair(className))
        return super.loadClass(className);
    try (InputStream unmodified = this.getResourceAsStream(className.replace(".", "/") + ".class")) {
        if (unmodified == null) {
            throw new ClassNotFoundException("类资源不存在: " + className);
        }
        // 读取原始字节码
        byte[] rawClassBytes = unmodified.readAllBytes();
        // 执行字节码修改
        ClassReader classReader = new ClassReader(rawClassBytes);
        ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_FRAMES);
        classReader.accept(new AccessRepairVisitor(classWriter), 0);
        byte[] modifiedClassBytes = classWriter.toByteArray();
        // 加载修改后的类
        return defineClass(className, modifiedClassBytes, 0, modifiedClassBytes.length);
    } catch (Exception e) {
        throw new ClassNotFoundException("修改类权限失败: " + className, e);
    }
}

3. 注意事项

  • ASM版本需要和你处理的类的编译JDK版本匹配,处理JDK8的类用ASM5以上即可,处理JDK17+的类需要用ASM9以上版本。
  • 如果需要连private成员也修改为public,直接去掉访问权限判断的条件即可。
  • 如果你需要修改JDK核心类库的类,需要打破双亲委派模型才能生效,普通业务类无需额外处理。
  • 修改完成后要保证类的父类、依赖的接口已经被对应类加载器加载,避免链接错误。

内容的提问来源于stack exchange,提问作者Luke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 07:00:05