我已经看到了有关此问题的几个问题,但它们是针对Netty的旧版本的。
我尝试了他们的答案,将org.jboss.netty与io.netty切换了出去,但是发生了同样的错误。
我正在尝试使用启用了Proguard的使用Netty 5.0.0Alpha2(内部版本16)的Android应用程序进行编译。
没有Proguard,该应用程序运行良好。
一旦启用Proguard,在尝试使用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)
...
这是我的Proguard配置:
# 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.**
我已经在没有-dontwarn选项的情况下对其进行了测试,以查看警告是否将我指向正确的方向,但是它们都缺少诸如slf4j和Tomcat之类的可选依赖项。
我也尝试过排除所有Netty类,例如:
-keep class io.netty.** {
*;
}
...但是这似乎也无法解决。
在阅读了一些相当大的Netty资料后,我已经通过一些谨慎的* Proguard规则解决了这个问题:
-keepattributes Signature,InnerClasses
-keepclasseswithmembers class io.netty.** {
*;
}
-keepnames class io.netty.** {
*;
}
我最初的异常是由从字节码中删除类型变量引起的,Netty通过反射使用了该变量。Signature
在-keepattributes
保留此信息。
如果仅这样做Signature
,您会得到一个略有不同的例外-keepattributes
- InnerClasses
通过在类文件中带回更多信息来添加解决此问题的方法。
后来,我得到了java.lang.NoSuchFieldException: ctl
;这就是-keepnames的目的。这样,仍然ctl
像Netty期望的那样调用该字段。
最后,ctl
由于Netty仅通过反射使用它们,所以某些成员(如前所述)已被Proguard删除。最终规则,-keepclasseswithmembers
确保Proguard不会将其删除。
如果采用这种方法,强烈建议您仅使用所需的Netty jar,而不要使用-all jar。从-all切换到只有所需的Netty的罐子把我的方法计数的方式下来,我已经走了过去的65K限制后。减少罐子需要一些反复试验,尽管分离尚不清楚,而且实际上没有任何资源可以说明是什么。
*一点也不仔细,我只是将规则拍入文件中,如果没有执行任何操作,则将其删除。可能有一种更好的方法可以将信息保留在整个程序中,而不是保留在整个程序中。
如果有人遇到此问题-“ <class>不是@Sharable处理程序,因此不能多次添加或删除。”,添加
*Annotation*
到-keepattributes列表中:-keepattributes Signature, InnerClasses, *Annotation*