Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are features of using Proguard in project with Protocol Buffers?

I have a project in where Google Protocol Buffers are used. Once I try to obfuscate it with ProGuard it seems that protobuf causes problem.

All my own classes I package into mybuildedclasses.jar. Google code is packaged into protbuf.jar

mybuildedclasses.jar
protobuf.jar
other external jars

After that I am trying to obfuscate mybuildedclasses.jar. Config file is similar to this one. Eventually all jars are packaged inside another fat jar.

I run the program and once message is tried to be sent this kind of Exceptions are printed.

 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.<init>(GeneratedMessage.java:1502)
        at com.google.protobuf.GeneratedMessage$FieldAccessorTable.<init>(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.<clinit>(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)

And

 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)

If I don't obfuscate then everything works perfectly. So how should particularly configure -keep option for Google Protocol Buffers related code?

I have tried for generated message files, but it give same exceptions.

-keep public class org.mypackage.messages.* {
 }
like image 975
Nikolay Kuznetsov Avatar asked Dec 31 '12 06:12

Nikolay Kuznetsov


1 Answers

It looks like this may just be a matter of the package being misaligned. Look at the error:

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

So that's org.mypackage.Control.

Now look at your Proguard configuration:

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

That's using org.mypackage.messages, which wouldn't include org.mypackage.Control.

Now presumably those aren't your real package names - but if they're representative, it sounds like you need to change your .proto file to emit classes in the package org.mypackage.messages instead of org.mypackage. (You could change your Proguard configuration instead, but it sounds like that would pick up too much.)

Alternatively, you might be able to just use the inheritance tree. I'm not a Proguard user myself, but judging by the examples, you might want:

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

I'd expect that to work on all your protocol buffer classes regardless of package. You may find that there are other fields/methods which protobuf expects in the "top level" class though.

EDIT: Looking at the documentation further, it may be that you need:

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

or

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

to preserve all members as well. There are other "keep" options which are looking at instead of -keep, such as -keepnames.

like image 155
Jon Skeet Avatar answered Nov 09 '22 17:11

Jon Skeet