0

我有简单的 POJO,每个属性都有 getter 和 setter。除了那些名为 id 和 serialNumber 的东西外,所有东西都被混淆了。

id 属性不会被重命名,它的 getter 和 setter 也不会。

serialNumber 属性确实被重命名,但它的 getter 和 setter 没有。

这些属性没有什么特别之处,我也没有在我的 Proguard 配置中添加任何东西来让 Proguard 以不同的方式对待它们。

我的 Proguard 配置

# Fudge around some issues
-dontskipnonpubliclibraryclasses

# Preserve all annotations.
-keepattributes *Annotation*

# Preserve all native method names and the names of their classes.
-keepclasseswithmembernames class * {
    native <methods>;
}

# Preserve the special static methods that are required in all enumeration
# classes.
-keepclassmembers class * extends java.lang.Enum {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# Explicitly preserve all serialization members. The Serializable interface
# is only a marker interface, so it wouldn't save them.
# You can comment this out if your application doesn't use serialization.
# If your code contains serializable classes that have to be backward 
# compatible, please refer to the manual.
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

# Keep some source file attributes so we have a chance of decoding stack traces
-renamesourcefileattribute SourceFile
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
        SourceFile,LineNumberTable,*Annotation*,EnclosingMethod

# make sure we keep info for downstream libraries
-dontshrink
-dontoptimize
-useuniqueclassmembernames

以及地图文件的输出

java.lang.String id -> id
  int productCode -> a
  int platform -> b
  java.lang.String model -> c
  java.lang.String serialNumber -> d
  java.lang.String machineID -> e
  java.lang.String parentSerialNumber -> f
  long clientTime -> g
  38:38:java.lang.String getId() -> getId
  47:48:void setId(java.lang.String) -> setId
  52:52:int getProductCode() -> a
  57:58:void setProductCode(int) -> a
  62:62:int getPlatform() -> b
  67:68:void setPlatform(int) -> b
  72:72:java.lang.String getModel() -> c
  77:78:void setModel(java.lang.String) -> a
  82:82:java.lang.String getSerialNumber() -> getSerialNumber
  87:88:void setSerialNumber(java.lang.String) -> setSerialNumber
  92:92:java.lang.String getMachineID() -> d
  97:98:void setMachineID(java.lang.String) -> b
  102:102:java.lang.String getParentSerialNumber() -> e
  107:108:void setParentSerialNumber(java.lang.String) -> c
  112:112:long getClientTime() -> f
  117:118:void setClientTime(long) -> a
4

2 回答 2

4

这是由于使用了该-useuniqueclassmembernames选项。

如果类成员名称必须全局对应(包括 Java 运行时库),则此选项将所有类中的所有类成员链接在一起。

这意味着,如果在一个类中有任何方法Foo#getName()被混淆a(),其他类中但具有相同名称的方法Bar#getName()也将映射到混淆名称a()

Foo.getName() -> Foo.a()
Bar.getName() -> Bar.a()

现在开始使用图书馆罐子。由于 ProGuard 还查看库 jar 以查找有关引用,因此它将扫描rt.jar类并找到以下类:

  • com/sun/servicetag/SystemEnvironment
  • java/security/cert/X509CertSelector
  • 等等

这些类也有方法方法:

  • com.sun.servicetag.SystemEnvironment.getSerialNumber()
  • java.security.cert.X509CertSelector.getSerialNumber()
  • 等等

这些成员被忽略以进行混淆,但它们的名称映射 ( getSerialNumber> getSerialNumber) 由 ProGuard 记录并由于 useUniqueClassMemberNames 配置选项而保存在描述符映射中。

供参考:我通过使用您的配置文件调试 ProGuard 发现了这一点。对于成员信息链接器,似乎是使用 AllMemberVisitor 而不是 BottomClassFilter 的情况,但我对 ProGuard 的内部如何工作并不确定。

于 2012-06-13T19:18:03.203 回答
3

该选项-useuniqueclassmembernames会执行此操作,以确保代码更改的混淆映射不会过时。未来的代码可能会为这个类和一些包含这些方法的库类添加一个公共接口。如果方法被重命名,这将破坏映射。

于 2012-06-13T19:20:53.043 回答