突然抛出Kryo ClassNotFoundException

时间:2016-11-09 15:02:53

标签: classnotfoundexception kryo

在阅读了很多帖子后,我没有找到kryo问题的答案。

我们正在尝试在我们的系统中实现Kryo(v4.0.0),它可以在两台服务器之间序列化/反序列化大量的消息。

我们的问题是序列化/反序列化可以在几分钟内正常工作(超过一千条消息)并突然停止使用以下异常:

2016-11-09 13:23:32,968 [AMQP_consumer_blk-ic-p.tradair.com_TMSOutWL_TMSOutWL_streaming-1] ERROR Driver handleDelivery -
com.esotericsoftware.kryo.KryoException: Unable to find class: ^AA^]^A^@^A^B^C^_^C ^C!^C^A59927910321794
Serialization trace:
payload (com.trade.common.messagebus.AMQPPacket)
        at com.esotericsoftware.kryo.util.DefaultClassResolver.readName(DefaultClassResolver.java:160) ~[kryo-shaded-4.0.0.jar:?]
        at com.esotericsoftware.kryo.util.DefaultClassResolver.readClass(DefaultClassResolver.java:133) ~[kryo-shaded-4.0.0.jar:?]
        at com.esotericsoftware.kryo.Kryo.readClass(Kryo.java:693) ~[kryo-shaded-4.0.0.jar:?]
        at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:118) ~[kryo-shaded-4.0.0.jar:?]
        at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:540) ~[kryo-shaded-4.0.0.jar:?]
        at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:813) ~[kryo-shaded-4.0.0.jar:?]
        at com.tradair.common.serialization.kryo.KryoSerializer.deserialize(KryoSerializer.java:60) ~[common-4.7.3.12.jar:?]
        at com.trade.common.messagebus.AbstractMessageBusConsumer$1.handleDelivery(AbstractMessageBusConsumer.java:106) ~[common-4.7.3.12.jar:?]
        at com.rabbitmq.client.impl.ConsumerDispatcher$5.run(ConsumerDispatcher.java:144) ~[amqp-client-3.4.3.jar:?]
        at com.rabbitmq.client.impl.ConsumerWorkService$WorkPoolRunnable.run(ConsumerWorkService.java:95) ~[amqp-client-3.4.3.jar:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_40]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_40]
        at java.lang.Thread.run(Thread.java:745) [?:1.8.0_40]
Caused by: java.lang.ClassNotFoundException: ^AA^]^A^@^A^B^C^_^C ^C!^C^A59927910321794
        at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[?:1.8.0_40]
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_40]
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[?:1.8.0_40]
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_40]
        at java.lang.Class.forName0(Native Method) ~[?:1.8.0_40]
        at java.lang.Class.forName(Class.java:348) ~[?:1.8.0_40]
        at com.esotericsoftware.kryo.util.DefaultClassResolver.readName(DefaultClassResolver.java:154) ~[kryo-shaded-4.0.0.jar:?]
        ... 12 more

你可以看到Kryo没有成功读取类名(无法找到类:^ AA ^] ^ A ^ @ ^ A ^ B ^ C ^ _ ^ C ^ C!^ C ^ A59927910321794)。< / p>

我的序列化课程:

public class KryoSerializer extends AbstractSerializer {

    private Logger logger = LoggerFactory.getLogger(KryoSerializer.class);
    protected Kryo kryo;
    protected Output output;
    protected Input input;
    protected ByteArrayOutputStream bos;
    protected ByteArrayInputStream bis;

    public KryoSerializer(List<Class> list) {
        kryo = new Kryo();
        kryo.setRegistrationRequired(false);
        kryo.setReferences(true);
        for (Class cl : list) {
            kryo.register(cl);
        }
    }

    @Override
    public <T> byte[] serialize(T msg) {
        try {
            bos = new ByteArrayOutputStream();
            output = new Output(bos);
            kryo.writeClassAndObject(output, msg);
            output.flush();
            return bos.toByteArray();
        } finally {
            try {
                if (output != null) {
                    output.close();
                }
                if (bos != null) {
                    bos.close();
                }
            } catch (IOException eio) {
                logger.warn("", eio);
            }
        }
    }

    @Override
    public <T> T deserialize(byte[] bytesArray) {
        try {
            bis = new ByteArrayInputStream(bytesArray);
            input = new Input(bis);
            return (T) kryo.readClassAndObject(input);
        } finally {
            try {
                if (input != null) {
                    input.close();
                }
                if (bis != null) {
                    bis.close();
                }
            } catch (IOException eio) {
                logger.warn("", eio);
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

据我所知,Kryo类不是线程安全的。如果您在并发环境中使用它,则必须每次都创建一个新实例。像这样:

bos = new ByteArrayOutputStream();
output = new Output(bos);
new Kryo().writeClassAndObject(output, msg);
output.flush();
return bos.toByteArray();

我曾经以这种方式解决类似的问题。