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

Proguard混淆静态Builder类时如何保留参数名称?

如何在Proguard混淆中保留静态Builder类的参数名称?

我明白你现在的痛点:用Builder模式写的静态内部类,经过Proguard混淆后,方法参数名甚至字段名都被替换成了无意义的符号,不管是调试还是依赖参数名的场景(比如反射、注解驱动的框架)都受影响。下面结合你提供的代码和配置,一步步解决这个问题:

原始Builder类代码

public class MyData {
    private final String name;
    private final int age;

    private MyData(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
    }

    public static class Builder {
        private String name;
        private int age;

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Builder age(int age) {
            this.age = age;
            return this;
        }

        public MyData build() {
            return new MyData(this);
        }
    }
}

混淆后的问题代码(参数名被替换)

public class MyData {
    private final String a;
    private final int b;

    private MyData(Builder var1) {
        this.a = var1.a;
        this.b = var1.b;
    }

    public static class Builder {
        private String a;
        private int b;

        public Builder a(String var1) {
            this.a = var1;
            return this;
        }

        public Builder b(int var1) {
            this.b = var1;
            return this;
        }

        public MyData build() {
            return new MyData(this);
        }
    }
}

你当前使用的Proguard配置

# 基本混淆规则
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

# 保留类名
-keepnames class com.example.MyData
-keepnames class com.example.MyData$Builder

问题分析

你的现有配置只保留了类的名称,但没有保留Builder类的方法参数名、字段名,也没开启参数元数据的保留。Proguard默认会混淆方法参数名,这就是你看到参数被替换成var1、字段被替换成a/b的原因。

解决方案:添加针对性的Proguard规则

根据你的需求,提供两种精准的配置方案:

方案1:完整保留Builder类的所有成员(适合需要完全保留结构的场景)

# 保留MyData类的核心构造方法,避免Builder无法实例化它
-keepclassmembers class com.example.MyData {
    private <init>(com.example.MyData$Builder);
}

# 完整保留Builder类的所有字段、方法,以及方法参数名
-keep class com.example.MyData$Builder {
    <fields>;
    <methods>;
    # 核心:保留方法参数的元数据(Java 8+支持)
    -keepattributes MethodParameters
}

# 如果使用了依赖参数名的注解,额外保留注解信息
-keepattributes RuntimeVisibleParameterAnnotations,RuntimeInvisibleParameterAnnotations

方案2:仅保留Builder的Setter方法参数名(更轻量化)

如果不需要保留所有字段,只需要保留Setter方法的参数名,可以用更精准的规则:

# 保留MyData的构造方法
-keepclassmembers class com.example.MyData {
    private <init>(com.example.MyData$Builder);
}

# 仅保留Builder的Setter方法及其参数名
-keepclassmembers class com.example.MyData$Builder {
    public ** name(java.lang.String);
    public ** age(int);
    # 核心:保留参数元数据
    -keepattributes MethodParameters
}

关键说明

  • -keepattributes MethodParameters是核心配置:它告诉Proguard保留方法参数名称的元数据,这是Java 8及以上版本支持的特性,没有这条规则,即使方法名保留了,参数名还是会被混淆。
  • 如果需要调试时看到更多信息,可以额外添加-keepattributes SourceFile,LineNumberTable来保留源文件名和行号。

添加上述规则后重新执行混淆,Builder类的参数名、字段名就会和原始代码一致,不会被替换了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:23:00