2012-08-09 48 views
5

Tôi cố gắng để serialize và deserialize đối tượng của một lớp tùy chỉnh (ví dụ, SomeClass, có một mặc định không-args constructor) vào một mảng byte[], sử dụng Kryo 2.19 và serializer mặc định (FieldSerializer).Generic Java serialization/deserialization sử dụng Kryo

Việc tuần tự hóa dường như hoạt động OK, nhưng tôi nhận được nhiều ngoại lệ khác nhau trong quá trình deserialization, tùy thuộc vào việc triển khai thực tế SomeClass.

Mã này trông giống như sau:

SomeClass object = getObject(); // Create and populate a new object of SomeClass 

Kryo kryo = new Kryo(); 
FieldSerializer<?> serializer = new FieldSerializer<SomeClass>(kryo, SomeClass.class); 
kryo.register(SomeClass.class, serializer); 

ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
Output output = new Output(stream); 

kryo.writeObject(output, object); 

output.close(); // Also calls output.flush() 

byte[] buffer = stream.toByteArray(); // Serialization done, get bytes 

// Deserialize the serialized object. 
object = kryo.readObject(new Input(new ByteArrayInputStream(buffer)), SomeClass.class); 

Một ví dụ về các trường hợp ngoại lệ Tôi nhận được là:

Exception in thread "main" java.lang.IncompatibleClassChangeError: Found interface org.objectweb.asm.MethodVisitor, but class was expected 
    at com.esotericsoftware.reflectasm.ConstructorAccess.insertConstructor(ConstructorAccess.java:89) 
    at com.esotericsoftware.reflectasm.ConstructorAccess.get(ConstructorAccess.java:70) 
    at com.esotericsoftware.kryo.Kryo.newInstantiator(Kryo.java:1009) 
    at com.esotericsoftware.kryo.Kryo.newInstance(Kryo.java:1059) 
    at com.esotericsoftware.kryo.serializers.FieldSerializer.create(FieldSerializer.java:228) 
    at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:217) 
    at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:629) 

Dường như các loại tham số là có vấn đề để deserialize. Để kiểm tra giả thiết này, đây là một thực hiện tham số của SomeClassgetObject():

class SomeClass<T extends Serializable> 
{ 
    private final T[] elements; 

    private final int first; 
    private final int second; 

    private SomeClass() 
    { 
     this.elements = null; 
     this.first = 0; 
     this.second = 0; 
    } 

    private SomeClass(T[] elements, int first, int second) 
    { 
     this.elements = elements; 
     this.first = first; 
     this.second = second; 
    } 
} 

SomeClass<?> getObject() 
{ 
    String[] elements = new String[] {"This is a test", "one"}; 

    return new SomeClass<String>(elements, 1, 2); 
} 

này serializes tốt, nhưng deserialization ném ngoại lệ sau (quan sát cách chữ cái đầu tiên của chuỗi là không được báo cáo trong các nguyên nhân ngoại lệ):

Exception in thread "main" com.esotericsoftware.kryo.KryoException: Unable to find class: his is a test 
Serialization trace: 
elements (net.cetas.parserserver.data.report.SourceDataReporter$SomeClass) 
    at com.esotericsoftware.kryo.util.DefaultClassResolver.readName(DefaultClassResolver.java:132) 
    at com.esotericsoftware.kryo.util.DefaultClassResolver.readClass(DefaultClassResolver.java:109) 
    at com.esotericsoftware.kryo.Kryo.readClass(Kryo.java:613) 
    at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:724) 
    at com.esotericsoftware.kryo.serializers.DefaultArraySerializers$ObjectArraySerializer.read(DefaultArraySerializers.java:338) 
    at com.esotericsoftware.kryo.serializers.DefaultArraySerializers$ObjectArraySerializer.read(DefaultArraySerializers.java:293) 
    at com.esotericsoftware.kryo.Kryo.readObjectOrNull(Kryo.java:702) 
    at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.read(FieldSerializer.java:521) 
    at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:221) 
    at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:629) 

Nếu lớp trên được thực hiện mà không tham số hóa (ví dụ, các mảng elements khai báo là một String[]), deserialization hoạt động như mong đợi.

Bất kỳ ý tưởng nào?

+1

Bạn có thể đăng 'Mã của SomeClass' tại đây không? Tôi nhớ rằng trong Kryo bạn nên đăng ký tất cả các lớp có thể được tuần tự hóa (ví dụ, nếu lớp của bạn sử dụng ArrayList, nó cũng phải được đăng ký). Một câu hỏi khác, nó có hoạt động cho một lớp cố ý đơn giản không? –

+0

Có vẻ như nó phải liên quan đến Generics. Lớp được tham số hóa, ví dụ: SomeClass với biến cá thể riêng T []. Nếu biến đó bị xóa, nó hoạt động. Nếu không, nhiều loại ngoại lệ được ném, tùy thuộc vào biến thể. – PNS

+1

Điều này nghe có vẻ như bạn nên sử dụng 'SomeClass ' – Dahaka

Trả lời

11
Exception in thread "main" java.lang.IncompatibleClassChangeError: Found interface org.objectweb.asm.MethodVisitor, but class was expected 

Vui lòng kiểm tra phiên bản ASM nào bạn đang sử dụng trong dự án của mình. MethodVisitor là một giao diện trong ASM lên đến 3,3. Sau phiên bản 4.0, đây là một lớp.

Links:

0

Hãy chắc chắn rằng bạn sử dụng phiên bản cùng lớp cho serialization và de-serialization. Nếu bạn tuần tự hóa bằng một phiên bản lớp và sử dụng phiên bản lớp khác (ví dụ như sau khi thêm hoặc xóa trường) thì lỗi này có khả năng xảy ra. Không có nghĩa là nó chỉ có thể xảy ra trong tình huống đó.