2016-10-26 3 views
1

Java에서 자체 serializer를 구현했습니다. 이것을 abcSerializer라고 부를 수 있습니다. 직렬화하려고하는 객체는 abc이며 Google 프로토콜 버퍼 클래스입니다.kryo를 사용하여 protobuf를 직렬화 할 때의 문제

이 개체를 직렬화하기 위해 kryo frame work를 사용하려고합니다. 연구와 구글 이상의 독서 후, 나는 kryo 시리얼 라이저를 계속 진행하기로 결정했다. 나는 어떤 시리얼 라이저도 지정하지 않았다. 그래서 kryo가 기본 시리얼 라이저를 선택한다고 가정한다. 내가의 writeObject 작업을 수행 할 때

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

}

는, 모두 잘 있습니다. 그러나 readObject 할 때 문제가 온다. Kyro는 아래 예외를 던집니다.

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 

위의 예외는 대부분 자체 설명입니다.

kryo 문서는 다음과 같습니다. ""특정 유형의 serializer는 Java 코드를 사용하여 해당 유형의 새 인스턴스를 만듭니다. FieldSerializer와 같은 Serializers는 일반적이므로 모든 클래스의 새 인스턴스 만들기를 처리해야합니다. 기본적으로 클래스에 0 인수 생성자가 있으면 ReflectASM 또는 reflection을 통해 호출됩니다. 그렇지 않으면 예외가 발생합니다. 제로 인수 constructor이 비공개 인 경우, setAccessible를 사용해 리플렉션을 통해 액세스하려고 시도합니다. 이것이 받아 들일 수 있다면 private zero argument 생성자는 Kryo가 공용 API에 영향을 미치지 않고 클래스의 인스턴스를 생성 할 수있게하는 좋은 방법입니다. ""

이제 두 가지 질문이 있습니다.

1) Google 프로토콜 버퍼 생성 클래스에 arg 생성자가 없습니다. 그러나 이것은 사적인 것처럼 보입니다. 위의 kryo 예외에 대한 근본적인 원인이 문제입니까?

2) 그렇다면 위의 문제를 어떻게 해결할 수 있습니까? 내 말은, 어떻게 내 serializer를 작성하고 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에서 인식되지 않는 클래스의 객체를 발견

, 그것은 다시 자바 직렬화에 떨어진다. 모든 효율적이지 않으며 때로는 작동하지 않습니다.

은 (글쎄, 나는 위에서 항상 진실하지 않을 수 있음을 고백합니다. 그것은 Kryo 구성의 일부가 될 수 있습니다. 그것은 내가 작동 환경에서 사실이다.)

당신이 사용하도록 말할 수는 특정 클래스에 대한 직렬화를 소유하고 있지만 특정 클래스에 대한 사용자 지정 serializer를 만들어 더 잘 수행 할 수 있습니다.

위의 내용은 Kryo 내에서 protobufs의 기존 직렬화를 활용합니다. 기본적으로 Kryo에서 직렬화를 처리하기 위해 기존 프로토 타입 writeTo()parseFrom()을 사용합니다. 위의 클래스를 등록하여 각 protobuf 클래스를 직렬화하십시오. (Protobuf 클래스는 GeneratedMessage까지 확장됩니다.)

개체를 쓰는 것은 정상적인 protobuf 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/explain-entire-code-based-answers)은 게시물의 품질을 향상시키는 데 정말로 도움이됩니다. 앞으로 독자의 질문에 답하고 있으며 코드 제안의 이유를 알지 못할 수도 있습니다. –

관련 문제