Proguard and Netty 5 on Android

别等时光非礼了梦想. 提交于 2021-01-03 08:38:12

问题


I've seen a couple questions regarding this issue, but they are for older versions of Netty.
I have tried their answers, switching org.jboss.netty out with io.netty, but the same error occurs.

I'm trying to compile an Android app that uses Netty 5.0.0Alpha2 (build #16) with Proguard enabled.

Without Proguard, the app runs fine.
As soon as I enable Proguard, I get this exception when it tries to use Netty:

java.lang.IllegalStateException: unknown type parameter 'I': class io.netty.channel.SimpleChannelInboundHandler
    at io.netty.util.internal.TypeParameterMatcher.find0(Unknown Source)
    at io.netty.util.internal.TypeParameterMatcher.find(Unknown Source)
    at io.netty.channel.SimpleChannelInboundHandler.<init>(Unknown Source)
    at io.netty.channel.SimpleChannelInboundHandler.<init>(Unknown Source)
    ...

This is my Proguard config:

# billing
-keep class com.android.vending.billing.**

# butterknife
-dontwarn butterknife.internal.**
-keep class **$$ViewInjector {
    *;
}
-keepnames class * {
    @butterknife.InjectView *;
}

# admob
-keep public class com.google.android.gms.ads.** {
    public *;
}

-keep public class com.google.ads.** {
    public *;
}

# logging
-assumenosideeffects class android.util.Log

# netty (partial)
-dontwarn io.netty.**
-dontwarn sun.**

I have tested it without the -dontwarn options to see if the warnings would point me in the right direction, but it's all missing optional dependencies like slf4j and Tomcat.

I have also tried excluding all the Netty classes like so:

-keep class io.netty.** {
    *;
}

...but that does not appear to fix it either.


回答1:


I have fixed this issue with some carefully* applied Proguard rules after reading through parts of the rather huge Netty sources:

-keepattributes Signature,InnerClasses
-keepclasseswithmembers class io.netty.** {
    *;
}
-keepnames class io.netty.** {
    *;
}

My original exception was caused by the type variables being removed from the bytecode, which Netty uses via reflection. Signature in -keepattributes keeps this information.

You get a slightly different exception if you only do Signature on -keepattributes - adding InnerClasses fixes this one by bringing back even more information in the class files.

Later, I got java.lang.NoSuchFieldException: ctl; that's what -keepnames is for. This way, the field is still called ctl like Netty expects.

Finally, some members (like ctl, seen earlier) were being removed by Proguard because Netty only uses them via reflection. The final rule, -keepclasseswithmembers, makes sure Proguard doesn't remove them.

If you take this approach, I strongly recommend you use only the Netty jars you need, instead of the -all jar. Switching from -all to just the required Netty jars brought my method count way down after I had gone past the 65k limit. Reducing your jars requires bit of trial-and-error though as the separation is unclear and there's not really any resources saying what's what.

* not carefully at all, I just slapped rules into the file and removed them if they did nothing. There's probably a better way to do this that doesn't keep this information in the entire program, but instead just Netty.



来源:https://stackoverflow.com/questions/27083667/proguard-and-netty-5-on-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!