Android上的Proguard和Netty 5

tcomlyy6  于 2024-01-04  发布在  Android
关注(0)|答案(3)|浏览(168)

我已经看到了一些关于这个问题的问题,但它们是针对旧版本的Netty的。
我试过他们的答案,把org.jboss.netty换成io.netty,但还是出现了同样的错误。
我试图编译一个Android应用程序,使用Netty 5.0.0Alpha2(构建#16)与Proguard启用。
没有Proguard,应用程序运行良好。
一旦我启用Proguard,当它尝试使用Netty时,我会得到这个异常:

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

字符串
这是我的Proguard配置:

  1. # billing
  2. -keep class com.android.vending.billing.**
  3. # butterknife
  4. -dontwarn butterknife.internal.**
  5. -keep class **$$ViewInjector {
  6. *;
  7. }
  8. -keepnames class * {
  9. @butterknife.InjectView *;
  10. }
  11. # admob
  12. -keep public class com.google.android.gms.ads.** {
  13. public *;
  14. }
  15. -keep public class com.google.ads.** {
  16. public *;
  17. }
  18. # logging
  19. -assumenosideeffects class android.util.Log
  20. # netty (partial)
  21. -dontwarn io.netty.**
  22. -dontwarn sun.**


我在没有-dontwarn选项的情况下测试了它,看看警告是否会为我指出正确的方向,但它都缺少可选的依赖项,如slf 4j和Tomcat。
我也试过排除所有的Netty类,如下所示:

  1. -keep class io.netty.** {
  2. *;
  3. }


但这似乎也解决不了问题。

lokaqttq

lokaqttq1#

在阅读了相当庞大的Netty来源的部分内容后,我已经通过一些仔细应用的Proguard规则解决了这个问题:

  1. -keepattributes Signature,InnerClasses
  2. -keepclasseswithmembers class io.netty.** {
  3. *;
  4. }
  5. -keepnames class io.netty.** {
  6. *;
  7. }

字符串
我最初的异常是由于从字节码中删除了类型变量引起的,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需要一些试错,因为分离不清楚,而且没有任何资源说什么是什么。

  • 一点也不小心,我只是把规则放入文件中,如果它们什么都不做,就把它们删除。可能有一个更好的方法来做到这一点,那就是不在整个程序中保留这些信息,而是只保留Netty。
展开查看全部
xcitsw88

xcitsw882#

Una的答案保留了太多的类,这使得我的应用程序比平常大1MB。所以我使用以下规则:

  1. # netty
  2. -keepclassmembernames class io.netty.buffer.AbstractByteBufAllocator {
  3. *;
  4. }
  5. -keepclassmembernames class io.netty.buffer.AdvancedLeakAwareByteBuf {
  6. *;
  7. }
  8. -keep public class io.netty.util.ReferenceCountUtil {
  9. *;
  10. }

字符串

8wigbo56

8wigbo563#

如果您使用的是R8完全模式,请将此添加到proguard规则中:

  1. -keepnames class * extends io.netty.channel.ChannelInboundHandlerAdapter
  2. -keepnames class * extends io.netty.channel.ChannelOutboundHandlerAdapter

字符串
关键是要保留那些泛型类型的类的类名,因为io.netty.util.internal.TypeParameterMatcher会尝试从类中获取泛型类型参数。异常本身表明netty无法从类名中找到类型参数“I”,因为R8 full模式剥离了类签名。因此TypeParameterMatcher抛出异常。

相关问题