proguard icon indicating copy to clipboard operation
proguard copied to clipboard

Shrink stage did not consider the reference in Signature, resulting in loss of generic information

Open threeloe opened this issue 3 years ago • 3 comments

my code just like this: ` OuterModel outerModel = new Gson().fromJson("{"test":[{"url":"google.com"}]}", OuterModel.class); UrlModel urlModel= outerModel.subUrlModels.get(0);

public class OuterModel {

@SerializedName("test")
public List<SubUrlModel> subUrlModels;

public List<SubUrlModel> getSubUrlModels() {
    return subUrlModels;
}

public void setSubUrlModels(List<SubUrlModel> subUrlModels) {
    this.subUrlModels = subUrlModels;
}

}

class SubUrlModel extends UrlModel {

}

`

SubUrlModel is a empty class that extends UrlModel, UrlModel is a common model class。

after I use proguard to process the code, I encountered the following error: java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.bytedance.android.model.UrlModel

I found that the SubUrlModel class was deleted, and the generic information was modified. But it is not correct, it is Objetct, it should actually be UrlModel

image

``

threeloe avatar Jun 24 '21 07:06 threeloe

Hi @threeloe ! Thanks for the report.

~~This seems like a known limitation with Gson optimization. There is a known limitation listed in the manual for GSON optimizations that's relevant here~~

ProGuard can not optimize the following use cases of Gson: ...

  • Serializing classes that have generic type variables in their signature.

You should be able to disable GSON optimization and instead use -keep rules for the model classes e.g.

-optimizations !library/gson
-keep class com.example.*Model {*; }

mrjameshamilton avatar Jun 24 '21 07:06 mrjameshamilton

@mrjameshamilton Thanks for the reply, I think this is not an error in the optimization phase, but a problem in the shrink phase. The problem can still be reproduced by adding the following configuration

-dontoptimize -dontobfuscate

Of course, keep SubUrlModel can solve my problem

threeloe avatar Jun 24 '21 13:06 threeloe

Indeed, you're right - I've checked further and the problem is shrinking. ProGuard cannot tell that SubUrlModel is used because it is used through reflection via Gson.

Since SubUrlModel is unused; the ClassShrinker changes the signature attribute here. It changes signature types to java/lang/Object if the existing class is unused; ideally it would change it to the next used super-type but currently it's not the case.

So, indeed the workaround here is to keep the SubUrlModel class to prevent it from being shrunk.

mrjameshamilton avatar Jun 24 '21 23:06 mrjameshamilton