4

I've migrated from google protobuf v. 2.4.1 to v. 2.5.0 (no other change).

I had a perfectly working client-server [android<>gae dev server] communication using 2.4.1.
Now with 2.5.0 it is broken.

Without any modification to the .proto file, I've setup my client and server with the new 2.5.0 jar, and with the new protoc executable I've generated a new source file for client and server from the same proto file.

Now I get this error on the server when I'm trying to parse the message:

VerifyError: class ... overrides final method getUnknownFields.()Lcom/google/protobuf/UnknownFieldSet;

full stack:

java.lang.VerifyError: class com.mta.pb.ACM$MyRequest overrides final method getUnknownFields.()Lcom/google/protobuf/UnknownFieldSet;
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at com.google.appengine.tools.development.IsolatedAppClassLoader.loadClass(IsolatedAppClassLoader.java:213)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:186)
at com.google.appengine.tools.development.agent.runtime.RuntimeHelper.checkRestricted(RuntimeHelper.java:70)
at com.google.appengine.tools.development.agent.runtime.Runtime.checkRestricted(Runtime.java:64)
**at com.mta.server.p.AndroidServletP.doPost(AndroidServletP.java:91)** <- my code
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
at com.googlecode.objectify.cache.AsyncCacheFilter.doFilter(AsyncCacheFilter.java:57)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    ...etc

Things I've already tried:

1) Reading the changelog, I've tried to change the parse code from:

            request = MyRequest.parseFrom(requstBlob); 

to

            request = MyRequest.PARSER.parseFrom(requstBlob); 

(this is the same line 91 that you see in the stack trace).
It didn't change a thing. Same error.

2) I've tried to parse the message manually:
I printed out the base64 string coming to the server, converted it into binary

base64 -d in64 > out64.bin

than

protoc --decode=MyRequest my.proto < out64.bin > tmp.txt

And it parses it perfectly. So the problem is only at the parsing part of the new protobuf.

3) I've tried taking ReqType out of MyRequest, no effect.

For reference: the relevant protobuf definition

/**
 * Master request object
 */
message MyRequest {
    optional RequestContext context = 1;
    optional MyReport myReport = 2;
    optional CategoryRequest catRequest = 3;
    optional GetMessage getMessage = 4;
    optional SearchRequest searchRequest = 5;
    enum ReqType {
        UNDEFINED = 1;
        REGISTER = 104;
        UPDATE = 123;
        GET_PAYLOAD = 100;
        SEARCH = 200;
        REPEAT_GCM = 623;
        REPEAT_PREPARE = 842;
    }
    optional ReqType reqType = 10;
    optional bool repeat = 11;
}

Any advice will be greatly appreciated!

Amir Uval
  • 14,425
  • 4
  • 50
  • 74

2 Answers2

8

I would guess you did not upgrade / recompile something. In protobuf 2.4.1 version in the jars.

in the GeneratedMessage class, getUnknownFields was a final method in 2.4.1 but in 2.5.0 it becomes:

  //@Override (Java 1.6 override semantics, but we must support 1.5)
  public UnknownFieldSet getUnknownFields() {
    throw new UnsupportedOperationException(
        "This is supposed to be overridden by subclasses.");
  }

and is overridden in the generated class. You may need to recompile all your classes that use generated protocol buffer classes.

Given the messages

java.lang.VerifyError: class com.mta.pb.ACM$MyRequest overrides final method getUnknownFields.()Lcom/google/protobuf/UnknownFieldSet;

This tells you you are running code generated with Protocol-Buffers 2.5.0 with a protocol-fuffers-2.4.1 (or earlier) jar.

Bruce Martin
  • 10,358
  • 1
  • 27
  • 38
  • Thanks. That was the first thing I've done. I have one generated file. After the upgrade, I deleted it (both from client and server), and re-compiled with protoc version 2.5.0. I also replaced the 2.4.1 jars in both client and server. (I've compiled the lib jars myself, I wonder if it's possible that the 2.5.0 lib itself got compiled with my than enabled 2.4.1...) – Amir Uval Apr 22 '13 at 16:23
  • An easy error to make is to recompile the Descriptor proto with the old protoc version. The error looks like there some reference to 2.4.1 hanging around somewhere. I can not suggest where though. – Bruce Martin Apr 22 '13 at 23:40
  • I compiled my descriptor.proto with the correct protoc to begin with. Unfortunately it's something else – Amir Uval Apr 23 '13 at 07:39
  • @Permaquid that's a new idea. You should make that a separate answer rather than a comment. – Amir Uval May 10 '14 at 19:17
  • @uval your messages indicates you are using Classes generated with 2.5 with a earlier (2.4.1) or earlier Protocol-Buffers jar; I will add this into the answer – Bruce Martin May 10 '14 at 23:21
  • Yes of course - I replaced the jars to 2.5.0 and with your suggestion I made sure that I re-compiled everything with 2.5.0, but it didn't solve my case. @Permaquid questions the assumption that the build setup is correct. I'm *almost* sure I verified that, but I'm not 100$ certain. Worth another try. – Amir Uval May 11 '14 at 07:45
  • Sorry, comment should be your messages indicates you are using Classes generated with 2.5.0 but you are running with a earlier (2.4.1) or earlier Protocol-Buffers jar. So check what jars are on the class path when you run the program. You should find that protocol-Buffers-2.4.1 (or earlier) in the class path. Protocol-Buffers-2.5.0 may be there as well – Bruce Martin May 11 '14 at 07:54
2

A similar thing happened to me when I was compiling an application after upgrading to 2.5. Eventually I realized that the old 2.4 jar was still in the same folder as the new 2.5 jar, and that the build system xml file was still referring to the old one. It was just a matter of being a little more careful - nothing mysterious was going on.

Permaquid
  • 1,950
  • 1
  • 14
  • 15