Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proguard obfuscation results in java.lang.IllegalArgumentException: class declares multiple JSON fields named "a"

Upon starting up my app logs two errors, but only after obfuscation. Without obfuscation there are no errors.

Unless I'm being misled, the errors are like:

class Property declares multiple JSON fields named a

and same for class PropertyDefinition.

05/18 03:33:19.465  java.lang.IllegalArgumentException: class PropertyDefinition declares multiple JSON fields named a:  
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:122)
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:72)
com.google.gson.Gson.getAdapter(Gson.java:349)
com.google.gson.Gson.toJson(Gson.java:574)
com.google.gson.Gson.toJson(Gson.java:561)
com.google.gson.Gson.toJson(Gson.java:516)
com.google.gson.Gson.toJson(Gson.java:496)
Property.a(SourceFile:210) <see comment in code below noting this code line>
Property.a(SourceFile:68)
bj.a(SourceFile:44)
aA.<init>(SourceFile:339)

05/18 03:33:19.479  java.lang.IllegalArgumentException: class Property declares multiple JSON fields named a:  
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:122)
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:72)
com.google.gson.Gson.getAdapter(Gson.java:349)
com.google.gson.Gson.fromJson(Gson.java:790)
com.google.gson.Gson.fromJson(Gson.java:757)
com.google.gson.Gson.fromJson(Gson.java:706)
com.google.gson.Gson.fromJson(Gson.java:678)
Property.a(SourceFile:75) <see comment in code below noting this code line>
bj.a(SourceFile:44)
aA.<init>(SourceFile:339)

Here is the section of the obfuscation map relevant to one of the nearly identical errors. I unobfuscated the class name "Property" here and above. I don't see the problem. I have no further experience with obfuscation so I don't know what to look for.

mypackage.Property:
    mypackage.PropertyDefinition rootElement -> a
    java.util.HashMap indexById -> a
    java.util.HashMap indexByKey -> b
    long nntgID -> a
    43:54:boolean equals(java.lang.Object) -> equals
    60:64:int hashCode() -> hashCode
    68:84:boolean check() -> a
    88:88:java.lang.String getFileName() -> a
    92:92:java.lang.String getDirectory() -> b
    101:102:java.lang.String getVersion() -> c
    107:107:java.util.HashMap getIdIndex() -> a
    112:112:java.util.HashMap getKeyIndex() -> b
    122:122:long getNntgID() -> a
    126:127:void setNntgID(long) -> a
    142:147:void setRootElement(mypackage.PropertyDefinition) -> a
    150:150:mypackage.PropertyDefinition getPropertyDefinitionById(java.lang.String) -> a
    154:154:mypackage.PropertyDefinition getPropertyDefinitionByKey(java.lang.String) -> b
    162:168:java.lang.String toString() -> toString
    210:214:void toFile() -> a

BTW, I have this section in my Proguard config already:

-keep class com.google.gson** { *; }
-keepclassmembers class com.google.gson** {
   *;
}

Any suggestions on where to start troubleshooting?

like image 716
MountainX Avatar asked May 18 '13 08:05

MountainX


People also ask

What is an illegalargumentexception in Java?

The JVM will throw IllegalArgumentException if we use a getXxx accessor that is incompatible with the target field's type. In our example, if we write nameField.getInt (person), the JVM throws this exception since the field is of type String and not int or Integer:

When does the JVM throw illegalargumentexception?

The JVM will throw IllegalArgumentException if we use a getXxx accessor that is incompatible with the target field's type. In our example, if we write nameField.getInt (person), the JVM throws this exception since the field is of type String and not int or Integer: As we've already seen, the getXxx methods support widening for the primitive types.

How to create a JSON object in Java?

Insert the required key-value pairs using the put () method of the JSONObject class. Write the created JSON object into a file using the FileWriter class as −. Following Java program creates a JSON object and writes it into a file named output.json.

What are the exceptions that the JVM can throw while accessing private fields?

Now, let's discuss the exceptions that the JVM can throw while accessing the private fields. 6.1. IllegalArgumentException The JVM will throw IllegalArgumentException if we use a getXxx accessor that is incompatible with the target field's type.


2 Answers

You seem to be specifying the ProGuard option -overloadaggressively in your proguard-project.txt. It overloads field names and method names to the same obfuscated names, e.g. 'a', as long as the signatures of the fields and methods are different. It's valid for class files, but GSON clearly doesn't like it, so you should avoid the option.

like image 161
Eric Lafortune Avatar answered Nov 08 '22 12:11

Eric Lafortune


The reason that only keeping the name of the class without preserving member names doesn't work is because the member names are what is causing the error. Proguard is renaming multiple members to the same name 'a', which is perfectly valid in classfiles. However, the tool you're using doesn't like having multiple members with the same name so it throws an error.

The solution is therefore to stop Proguard from renaming the members of that class. There's probably also a Proguard setting to avoid duplicate names, but I'm not familiar enough to say what it is.

like image 30
Antimony Avatar answered Nov 08 '22 12:11

Antimony