Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache Thrift C GLib->;Java反序列化问题_Java_C_Serialization_Deserialization_Thrift - Fatal编程技术网

Apache Thrift C GLib->;Java反序列化问题

Apache Thrift C GLib->;Java反序列化问题,java,c,serialization,deserialization,thrift,Java,C,Serialization,Deserialization,Thrift,我无法在使用C GLib序列化的Java Thrift对象中反序列化。 我的序列化代码如下(我在提出问题后提出的解决方案): Java中的反序列化代码: TDeserializer deserializer = new TDeserializer(); ExceptionData ex = new ExceptionData(); try { byte[] binData = tuple.getBinary(0); _logger.info("Bin data length:

我无法在使用C GLib序列化的Java Thrift对象中反序列化。 我的序列化代码如下(我在提出问题后提出的解决方案):

Java中的反序列化代码:

TDeserializer deserializer = new TDeserializer();
ExceptionData ex = new ExceptionData();

try {
    byte[] binData = tuple.getBinary(0);

    _logger.info("Bin data length: " + binData.length);
    _logger.info("HEX data: " + DatatypeConverter.printHexBinary(binData));

    deserializer.deserialize(ex, binData);
} catch (TException e) {
    _logger.error(e);
}

_logger.info("Deserialized object: " + ex);
它总是失败,例外情况类似于:

org.apache.thrift.protocol.TProtocolException: Required field 'caught' was not found in serialized data!
我的节俭计划是:

struct ExceptionData {
    1: required string ex_sign, // exception signature
    2: required string cl_sign, // class signature where exception was thrown
    3: required bool caught // whether exception was caught or not
}
发送和接收的消息长度相同。但不知何故,在Java方面,我无法复制对象

可能有人遇到过类似的问题

UPD:

样本输出:

ExceptionData("Ljava/lang/ClassNotFoundException;", "Ljava/net/URLClassLoader;", true)
HEX data: 40890DE0297F00004C000000800000000100000000000000010000000000000000000000000000000000000000000000007E0DE0297F00000100000000000000000000000000000090D900E0
HEX data(1): 00880D109D7F00004E000000800000000100000000000000010000000000000000000000000000000000000000000000007E0D109D7F000001000000000000000000000000000000507F0D109D7F
HEX data(2): 00880D4CF57F00004E000000800000000100000000000000010000000000000000000000000000000000000000000000007E0D4CF57F000001000000000000000000000000000000507F0D4CF57F
我注意到上面的输出有一些奇怪的东西:

  • 为什么对于相同的输入数据,它会序列化为不同的输出
  • 为什么有这么多零
  • 我尝试仅使用Java对同一对象进行序列化反序列化,这是示例输出:

    ExceptionData("Ljava/lang/ClassNotFoundException;", "Ljava/net/URLClassLoader;", true)
    HEX data: 0B0001000000224C6A6176612F6C616E672F436C6173734E6F74466F756E64457863657074696F6E3B0B0002000000194C6A6176612F6E65742F55524C436C6173734C6F616465723B0200030100
    
    如果我只使用Java对象,则正确地序列化反序列化,并且对于相同的输入数据,十六进制输出是相同的

    UPD2:

    在发送到卡夫卡之前,对相同的tbuffer->buf连续进行了两次十六进制转储。发送前,缓冲区似乎包含错误的数据:

    call 1 buf:
      0000  00 88 0d 2c ce 7f 00 00 4e 00 00 00 80 00 00 00  ...,....N.......
      0010  01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00  ................
      0020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
      0030  00 7e 0d 2c ce 7f 00 00 01 00 00 00 00 00 00 00  .~.,............
      0040  00 00 00 00 00 00 00 00 50 e2 00 2c ce 7f        ........P..,..
    
    
    call 2 buf:
      0000  80 88 0d b8 08 7f 00 00 4e 00 00 00 80 00 00 00  ........N.......
      0010  01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00  ................
      0020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
      0030  00 e1 00 b8 08 7f 00 00 01 00 00 00 00 00 00 00  ................
      0040  00 00 00 00 00 00 00 00 20 88 0d b8 08 7f        ........ .....
    

    最后我发现错误在哪里。序列化数据存储在tbuffer->buf->data中,而不是tbuffer->buf。缓冲区长度存储在tbuffer->buf->len

    因此,最终工作代码是:

    ThriftMemoryBuffer* tbuffer = g_object_new(THRIFT_TYPE_MEMORY_BUFFER,
        "buf_size", 2048, NULL);
    ThriftTransport *transport = NULL;
    ThriftProtocol* protocol = NULL;
    GError* error = NULL;
    
    if (tbuffer) {
        transport = THRIFT_TRANSPORT(tbuffer);
        thrift_transport_open(transport, &error);
    
        protocol =
        THRIFT_PROTOCOL(
            g_object_new(THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL));
    
        if (protocol) {
            ExceptionData* exception_data = g_object_new(TYPE_EXCEPTION_DATA, "ex_sign",
                exception_signature, "cl_sign", class_signature, "caught",
                catch_method != NULL,
                NULL);
    
            if (exception_data) {
                ThriftStructClass* cls = THRIFT_STRUCT_CLASS(EXCEPTION_DATA_GET_CLASS(exception_data));
                cls->write(exception_data, protocol, &error);
    
                if(tbuffer->buf != NULL) {
    
                    printf("Buffer length %i bytes\n", tbuffer->buf->len);
    
                    send_kafka_message((const void *)tbuffer->buf->data, tbuffer->buf->len);
                }
    
                g_object_unref(exception_data);
            }
    
            g_object_unref(protocol);
        }
    
        if (thrift_transport_is_open(transport)) {
            thrift_transport_close(transport, &error);
        }
    
        g_object_unref(tbuffer);
    }
    

    所有字段都标记为
    必需
    。除了这是否是一个好的决定之外,
    required
    的意思是:字段必须存在于要反序列化的数据流中。大多数实现在反序列化之前和之后检查
    必需的
    成员的存在,这就是您在这里看到的。我们可以看到一个数据示例吗?打印的十六进制值可能增加了示例输出和问题中的一些注释(UPD之后)。第一个数据点(那个些有许多零的)是完全错误的。要么是在将缓冲区内容从C/glib传输到Java的过程中出现了问题,要么是缓冲区内容本身从一开始就是错误的。数据看起来像是一些反序列化内存,其中包含一些指针,因此在某个点上可能缺少指针解引用,或者是地址运算符。或者像那样的。是的,看起来像那样。在客户端(UPD2)的序列化之后添加了缓冲区的十六进制转储,尝试使用c_lib时,我意识到几乎没有可用的文档。如果我可以问的话,你是如何发现如何使用图书馆的?
    
    ThriftMemoryBuffer* tbuffer = g_object_new(THRIFT_TYPE_MEMORY_BUFFER,
        "buf_size", 2048, NULL);
    ThriftTransport *transport = NULL;
    ThriftProtocol* protocol = NULL;
    GError* error = NULL;
    
    if (tbuffer) {
        transport = THRIFT_TRANSPORT(tbuffer);
        thrift_transport_open(transport, &error);
    
        protocol =
        THRIFT_PROTOCOL(
            g_object_new(THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL));
    
        if (protocol) {
            ExceptionData* exception_data = g_object_new(TYPE_EXCEPTION_DATA, "ex_sign",
                exception_signature, "cl_sign", class_signature, "caught",
                catch_method != NULL,
                NULL);
    
            if (exception_data) {
                ThriftStructClass* cls = THRIFT_STRUCT_CLASS(EXCEPTION_DATA_GET_CLASS(exception_data));
                cls->write(exception_data, protocol, &error);
    
                if(tbuffer->buf != NULL) {
    
                    printf("Buffer length %i bytes\n", tbuffer->buf->len);
    
                    send_kafka_message((const void *)tbuffer->buf->data, tbuffer->buf->len);
                }
    
                g_object_unref(exception_data);
            }
    
            g_object_unref(protocol);
        }
    
        if (thrift_transport_is_open(transport)) {
            thrift_transport_close(transport, &error);
        }
    
        g_object_unref(tbuffer);
    }