2016-11-09 234 views
0

阅读了很多帖子之后,我没有找到答案与我的问题与kryo。Kryo ClassNotFoundException突然抛出

我们正在尝试在我们的系统中实现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)。

我的连载类:

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); 
      } 
     } 
    } 
} 

回答

0

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

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

我以前用这种方法解决了类似的问题。

相关问题