【问题标题】:Writing a ChannelBuffer to a Netty Channel throws java.io.NotSerializableException将 ChannelBuffer 写入 Netty Channel 会引发 java.io.NotSerializableException
【发布时间】:2012-06-09 14:11:18
【问题描述】:

我想将原始字节写入网络通道。我想我可以先创建一个 ChannelBuffer,用字节填充它(例如,来自 Kryo 序列化器),然后将该 ChannelBuffer 写入 netty Channel。

这是相关代码,我只是将一些字节填充到 ctor 中的 ChannelBuffer 并尝试在连接时发送它:

/**
 * Handler implementation for the object echo client.  It initiates the
 * ping-pong traffic between the object echo client and server by sending the
 * first message to the server.
 */
public class ObjectEchoClientHandler extends SimpleChannelUpstreamHandler {

private final ChannelBuffer firstMessage;

/**
 * Creates a client-side handler.
 */
public ObjectEchoClientHandler(int firstMessageSize) {
    if (firstMessageSize <= 0) {
        throw new IllegalArgumentException(
                "firstMessageSize: " + firstMessageSize);
    }
    firstMessage = ChannelBuffers.buffer(8192);
    for (int i = 0; i < firstMessageSize; i++) {
        firstMessage.writeByte(i % 256);
    }
}

@Override
public void channelConnected(
        ChannelHandlerContext ctx, ChannelStateEvent e) {

    // Send the first message if this handler is a client-side handler.
    // e.getChannel().write(firstMessage);
    Channels.write(ctx, e.getFuture(), firstMessage);
}

}

这似乎不起作用,因为它抛出了这个异常:

java.io.NotSerializableException: org.jboss.netty.buffer.BigEndianHeapChannelBuffer
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
at org.jboss.netty.handler.codec.serialization.ObjectEncoder.encode(ObjectEncoder.java:80)
at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.handleDownstream(OneToOneEncoder.java:61)
at org.jboss.netty.channel.Channels.write(Channels.java:626)
at org.jboss.netty.channel.Channels.write(Channels.java:587)
at ca.gsimard.spacecraft.client.ObjectEchoClientHandler.channelConnected(ObjectEchoClientHandler.java:83)
at ca.gsimard.spacecraft.client.ObjectEchoClientHandler.handleUpstream(ObjectEchoClientHandler.java:75)
at org.jboss.netty.channel.Channels.fireChannelConnected(Channels.java:227)
at org.jboss.netty.channel.socket.nio.NioWorker$RegisterTask.run(NioWorker.java:784)
at org.jboss.netty.channel.socket.nio.NioWorker.processRegisterTaskQueue(NioWorker.java:250)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:192)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)

我确信这很简单,而且可能是错误的做法,因为我似乎找不到与此相同错误的人。我现在使用的是 Netty 3.3.0。

我可以通过创建一个适当大小的 byte[] 并将 ChannelBuffer 的内容复制到它来使其工作,但我希望有一个更直接的解决方案来避免无用的字节复制。

    byte[] array = new byte[firstMessage.writerIndex()];
    firstMessage.readBytes(array);
    e.getChannel().write(array);

感谢任何指点!

【问题讨论】:

    标签: netty


    【解决方案1】:

    查看您的堆栈跟踪,我观察到以下两行:

    at org.jboss.netty.handler.codec.serialization.ObjectEncoder.encode(ObjectEncoder.java:80)
    at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.handleDownstream(OneToOneEncoder.java:61
    

    这对我来说意味着你的管道包含一个ObjectEncoder,它试图序列化一个ChannelBuffer。由于您的对象已经被 Kryo 编码,因此您不需要 ObjectEncoder。

    或者换一种说法(没有 Kryo),ChannelBuffer 应该是 ObjectEncoder 的 输出,而你的对象应该是输入。

    最好的办法是编写一个新的ChannelHandler,使用 Kryo 对您的对象进行编码。当 Kryo 作为 Netty 管道中的处理程序工作时,您可能会发现一些额外的效率。

    【讨论】:

    • 现在我正在浏览 netty 的源代码和文档,这一切都说得通了。谢谢!
    • Channelbuffer 是否可序列化?我遇到了java.io.NotSerializableException: org.jboss.netty.buffer.BigEndianHeapChannelBuffer 异常,但是当我删除了该类的 ChannelBuffer 数据成员并将其替换为字节数组时,它起作用了。
    • ChannelBuffer 不可序列化。
    猜你喜欢
    • 2015-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-18
    • 2012-02-05
    • 2015-11-26
    相关资源
    最近更新 更多