在使用Protocol Buffers的项目中使用Proguard有什么特点?

我有一个使用Google Protocol Buffers的项目。 一旦我尝试使用ProGuard对其进行模糊处理,似乎protobuf会导致问题。

我将自己的所有类打包到mybuildedclasses.jar 。 Google代码打包到protbuf.jar

 mybuildedclasses.jar protobuf.jar other external jars 

之后我试图混淆mybuildedclasses.jar 。 配置文件与此类似。 最终所有的jar子都装在另一个胖jar子里面。

我运行程序,一旦尝试发送消息,就会打印出这种exception。

  Caused by: java.lang.RuntimeException: Generated message class "org.mypackage.messages.Control$MessageControlHandCard$Builder" missing method "getCardId". at com.google.protobuf.GeneratedMessage.getMethodOrDie(GeneratedMessage. java:1366) at com.google.protobuf.GeneratedMessage.access$1(GeneratedMessage.java:1 361) at com.google.protobuf.GeneratedMessage$FieldAccessorTable$SingularField Accessor.(GeneratedMessage.java:1502) at com.google.protobuf.GeneratedMessage$FieldAccessorTable.(Genera tedMessage.java:1441) at org.mypackage.Control$1.assignDescriptors(SourceFile:32 20) at com.google.protobuf.Descriptors$FileDescriptor.internalBuildGenerated FileFrom(Descriptors.java:300) at org.evogame.common.messages.Control.(SourceFile:3278) ... 60 more Caused by: java.lang.NoSuchMethodException: org.evogame.common.messages.Control$ MessageControlHandCard$Builder.getCardId() at java.lang.Class.getMethod(Class.java:1622) at com.google.protobuf.GeneratedMessage.getMethodOrDie(GeneratedMessage. java:1364) 

  Exception in thread "AWT-EventQueue-0" java.lang.ExceptionInInitializerError at org.mypackage.messages.Control$MessageControlGameRequest.interna lGetFieldAccessorTable(SourceFile:527) at com.google.protobuf.GeneratedMessage.getAllFieldsMutable(GeneratedMes sage.java:105) at com.google.protobuf.GeneratedMessage.getAllFields(GeneratedMessage.ja va:153) at com.google.protobuf.TextFormat$Printer.print(TextFormat.java:229) at com.google.protobuf.TextFormat$Printer.access$2(TextFormat.java:226) at com.google.protobuf.TextFormat.print(TextFormat.java:69) at com.google.protobuf.TextFormat.printToString(TextFormat.java:116) at com.google.protobuf.AbstractMessage.toString(AbstractMessage.java:87) 

如果我不混淆那么一切都很完美。 那么应该如何为Google Protocol Buffers相关代码特别配置-keep选项呢?

我已尝试生成消息文件,但它提供相同的例外。

 -keep public class org.mypackage.messages.* { } 

看起来这可能只是包裹未对齐的问题。 看看错误:

  Caused by: java.lang.RuntimeException: Generated message class "org.mypackage.Control$MessageControlHandCard$Builder" missing method "getCardId". ... 

这就是org.mypackage.Control

现在看看你的Proguard配置:

 -keep public class org.mypackage.messages.* { } 

那是使用org.mypackage.messages ,它不包括org.mypackage.Control

现在大概那些不是你真正的包名 – 但如果它们具有代表性,听起来你需要更改.proto文件以在org.mypackage.messages包中发出类而不是org.mypackage 。 (你可以改变你的Proguard配置,但听起来会觉得太多了。)

或者,您可以只使用inheritance树。 我自己不是Proguard用户,但从示例来看,您可能需要:

 -keep public class * extends com.google.protobuf.GeneratedMessage 

无论封装如何,我都希望能够处理所有协议缓冲区类。 您可能会发现protobuf在“顶级”类中还有其他字段/方法。

编辑:进一步查看文档,可能需要:

 -keep public class * extends com.google.protobuf.GeneratedMessage { *; } 

保留所有成员。 还有其他“保持”选项正在查看而不是-keepnames ,例如-keepnames

我更喜欢指定字段名称而不是保留整个类成员,这会产生更小的输出。

 -keepclassmembers your.class.name { int sampleIntField; String sampleStringField; }