【问题标题】:Protobuf 2.5.0 bug?Protobuf 2.5.0 错误?
【发布时间】:2013-04-14 09:32:06
【问题描述】:

我已经从 google protobuf v. 2.4.1 迁移到 v. 2.5.0(没有其他变化)。

我使用 2.4.1 进行了完美的客户端-服务器 [androidgae 开发服务器] 通信。
现在有了 2.5.0,它就坏了。

没有对 .proto 文件进行任何修改,我已经使用新的 2.5.0 jar 设置了我的客户端和服务器,并且使用新的 protoc 可执行文件,我从同一个 proto 为客户端和服务器生成了一个新的源文件文件。

现在我在尝试解析消息时在服务器上收到此错误:

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

全栈:

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

我已经尝试过的事情:

1) 阅读更改日志,我尝试将解析代码更改为:

            request = MyRequest.parseFrom(requstBlob); 

            request = MyRequest.PARSER.parseFrom(requstBlob); 

(这与您在堆栈跟踪中看到的第 91 行相同)。
它没有改变任何事情。同样的错误。

2) 我尝试手动解析消息:
我打印出传入服务器的base64字符串,将其转换为二进制

base64 -d in64 > out64.bin

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

它完美地解析它。 所以问题只出在新protobuf的解析部分。

3) 我尝试将 ReqType 从 MyRequest 中取出,但没有效果。

供参考:相关的protobuf定义

/**
 * 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;
}

任何建议将不胜感激!

【问题讨论】:

  • 几个小时徒劳无功的研究我已经回滚到 2.4.1,它又可以正常工作了。

标签: android google-app-engine protocol-buffers


【解决方案1】:

我猜你没有升级/重新编译一些东西。在 protobuf 2.4.1 版本的 jars 中。

GeneratedMessage 类中,getUnknownFields 是 2.4.1 中的最终方法,但在 2.5.0 中它变为:

  //@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.");
  }

并在生成的类中被覆盖。您可能需要重新编译所有使用生成的协议缓冲区类的类。

给定消息

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

这表明您正在运行代码生成,使用 Protocol-Buffers 2.5.0 和 protocol-fuffers-2.4.1(或更早版本)jar

【讨论】:

  • 谢谢。那是我做的第一件事。我有一个生成的文件。升级后,我删除了它(从客户端和服务器),并使用 protoc 版本 2.5.0 重新编译。我还替换了客户端和服务器中的 2.4.1 jar。 (我自己编译了 lib jar,我想知道 2.5.0 lib 本身是否有可能使用我启用的 2.4.1 编译...)
  • 一个容易犯的错误是用旧的 protoc 版本重新编译 Descriptor proto。该错误看起来像是对 2.4.1 的一些引用在某处徘徊。我不能建议在哪里。
  • 我一开始就用正确的协议编译了我的descriptor.proto。不幸的是,这是另一回事
  • @Permaquid 这是一个新想法。您应该将其作为单独的答案而不是评论。
  • @uval 您的消息表明您正在使用 2.5 生成的类和更早的 (2.4.1) 或更早的协议缓冲区 jar;我会将其添加到答案中
【解决方案2】:

当我升级到 2.5 后编译应用程序时,也发生了类似的事情。最终我意识到旧的 2.4 jar 仍然与新的 2.5 jar 在同一个文件夹中,并且构建系统 xml 文件仍然指的是旧的。只是要小心一点 - 没有什么神秘的事情发生。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    • 2019-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-13
    相关资源
    最近更新 更多