2016-10-26 2 views
1

Я реализовал свой собственный сериализатор на Java. Позволяет называть это как abcSerializer. Объектом, который я пытаюсь выполнить сериализацией, является abc, который является классом буфера протокола Google.Проблема в сериализации protobuf с использованием kryo

Я пытаюсь использовать работу кадра kryo для сериализации этого объекта. После небольшого исследования и чтения через google, я решил, что продолжить работу с сериализатором kryo. Я не определял какой-либо сериализатор как таковой, поэтому я предполагаю, что kryo выбирает сериализатор по умолчанию.

public class abcSerializer implements AttributeSerializer <abc> { 

    public abcSerializer() { 
     kryo = new Kryo(); 
    } 

    public static Kryo getKryo() { 
     return kryo; 
    } 

    @Override 
    public abc read(byte[] buffer) { 

    abc xyz = null; 

    ByteArrayInputStream abcsStream = new ByteArrayInputStream(buffer); 
    Input abcsStreamInput = new Input(abcsStream); 
    xyz = getKryo().readObject(abcsStreamInput, abc.class); 
    return xyz; 
} 

@Override 
public void write(byte[] buffer, abc abc) { 

    ByteArrayOutputStream abcStream = new ByteArrayOutputStream(); 
    Output abcOutput = new Output(abcStream); 

    getKryo().writeObject(abcOutput, abc); 

    abcOutput.toBytes()   
} 

}

Когда я writeObject, все хорошо. Однако проблема возникает, когда я читаю Object. Исключение составляет Киро.

com.esotericsoftware.kryo.KryoException: Class cannot be created (missing no-arg constructor): java.util.Collections$Unmodifiabljava.lang.IllegalStateException: Encountered error in deserializer [null value returned]. Check serializer compatibility.eRandomAccessList 

Вышеуказанное исключение в значительной степени сам пояснительный.

Документация крио приведена ниже. «Сериализаторы для определенного типа используют Java-код для создания нового экземпляра этого типа. Сериализаторы, такие как FieldSerializer, являются общими и должны обрабатывать создание нового экземпляра любого класса. По умолчанию, если класс имеет конструктор с нулевым аргументом, он вызывается через ReflectASM или отражение, в противном случае создается исключение. Если конструктор нулевого аргумента является закрытым, делается попытка получить доступ к нему посредством отражения с помощью setAccessible. Если это приемлемо, конструктор с частными аргументами является хорошим способом разрешить Kryo создавать экземпляры класса, не затрагивая публичный API. ""

Теперь у меня есть два вопроса.

1) Сгенерированный класс буфера протокола Google не имеет конструктора arg. Однако это кажется закрытым. Является ли это проблемой и основной причиной для вышеупомянутого исключения kryo?

2) Если да, то как двигаться вперед по вышеуказанной проблеме? Я имею в виду, как я могу написать собственный сериализатор и по-прежнему использовать для сериализации данных объекта буфера протокола Google?

ответ

0

Как это работает для вас?

/** 
* This lets Kryo serialize protobufs more efficiently. 
*/ 
public class ProtobufKryo<P extends GeneratedMessage> extends Serializer<P> { 
    protected final Method parser; 

    public ProtobufKryo(Class<P> theClass) { 
     try { 
      parser = theClass.getDeclaredMethod("parseFrom", InputStream.class); 
      parser.setAccessible(true); 
     } catch (NoSuchMethodException e) { 
      throw new IllegalArgumentException(theClass.toString() + " doesn't have parser"); 
     } 
    } 

    @Override 
    public void write(Kryo kryo, Output output, P generatedMessage) { 
     try { 
      generatedMessage.writeTo(output); 
     } catch (IOException e) { 
      // This isn't supposed to happen with a Kryo output. 
      throw new RuntimeException(e); 
     } 
    } 

    @Override 
    public P read(Kryo kryo, Input input, Class<P> gmClass) { 
     try { 
      return (P)parser.invoke(null, input); 
     } catch (InvocationTargetException | IllegalAccessException e) { 
      // These really shouldn't happen 
      throw new IllegalArgumentException(e); 
     } 
    } 
} 

OK ,, некоторые пояснения ....

Когда Kryo встречает объект класса он не признает, он возвращается к Java сериализации. Не каждый эффективный, а иногда и не работает.

(Ну, я признаюсь, что выше, не всегда может быть правдой. Это может быть частью конфигурации Kryo. Это является правды в среде я работаю в.)

Вы можете сказать ему, чтобы использовать его собственную сериализацию для определенных классов, но иногда вы можете добиться большего, создав собственный сериализатор для определенных классов.

Вышеупомянутая сериализация протобуфов в пределах Kryo. В основном, он использует существующие protobuf writeTo() и parseFrom() для обработки сериализации внутри Kryo. Вы зарегистрировали бы этот класс для сериализации каждого из ваших классов protobuf. (Классы Protobuf распространяются на GeneratedMessage.)

Списав объект, используется обычный протобуф writeTo().Чтение в protobuf использует классы parseFrom() метод, который найден через отражение в конструкторе.

Таким образом, вы бы настроить сериалайзер что-то вроде:

Kryo k = new Kryo(); 
    k.addDefaultSerializer(MyProtobuf.class, ProtobufKryo.class); 
    k.addDefaultSerializer(MyOtherProtobuf.class, ProtobufKryo.class); 

и т.д.

+2

Хотя этот фрагмент кода может решить вопрос, [включая пояснения] (Http: //meta.stackexchange .com/questions/114762/explaining-whole-code-based-answers) действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин вашего предложения кода. –

Смежные вопросы