我已经看到了一些关于这个问题的问题,但它们是针对旧版本的Netty的。
我试过他们的答案,把org.jboss.netty换成io.netty,但还是出现了同样的错误。
我试图编译一个Android应用程序,使用Netty 5.0.0Alpha2(构建#16)与Proguard启用。
没有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选项的情况下测试了它,看看警告是否会为我指出正确的方向,但它都缺少可选的依赖项,如slf 4j和Tomcat。
我也试过排除所有的Netty类,如下所示:
-keep class io.netty.** {
*;
}
型
但这似乎也解决不了问题。
3条答案
按热度按时间lokaqttq1#
在阅读了相当庞大的Netty来源的部分内容后,我已经通过一些仔细应用的Proguard规则解决了这个问题:
字符串
我最初的异常是由于从字节码中删除了类型变量引起的,Netty通过反射使用字节码。
-keepattributes
中的Signature
保留了此信息。如果只在
-keepattributes
上执行Signature
,则会出现稍微不同的异常-添加InnerClasses
可以通过在类文件中带回更多信息来修复这个异常。后来,我得到了
java.lang.NoSuchFieldException: ctl
;这就是-keepnames的作用。这样,该字段仍然被称为ctl
,就像Netty期望的那样。最后,一些成员(如前面看到的
ctl
)被Proguard删除,因为Netty只通过反射使用它们。最后一条规则-keepclasseswithmembers
确保Proguard不会删除它们。如果你采用这种方法,我强烈建议你只使用你需要的Netty jar,而不是-all jar。从-all切换到只需要Netty jar,在我超过65 k的限制后,我的方法计数 * 方式 * 下降了。减少你的jar需要一些试错,因为分离不清楚,而且没有任何资源说什么是什么。
xcitsw882#
Una的答案保留了太多的类,这使得我的应用程序比平常大1MB。所以我使用以下规则:
字符串
8wigbo563#
如果您使用的是R8完全模式,请将此添加到proguard规则中:
字符串
关键是要保留那些泛型类型的类的类名,因为
io.netty.util.internal.TypeParameterMatcher
会尝试从类中获取泛型类型参数。异常本身表明netty无法从类名中找到类型参数“I”,因为R8 full模式剥离了类签名。因此TypeParameterMatcher
抛出异常。