2009-08-24 14 views
18

Có cách nào để xác định số được tạo ra serialVersionUID của một đối tượng Java được tuần tự hóa không?Tìm serialVersionUID của đối tượng được tuần tự

Vấn đề là tôi đã tuần tự hóa một đối tượng mà không chỉ định rõ ràng serialVersionUID. Bây giờ quá trình deserialization phàn nàn về không tương thích lớp. Tuy nhiên tôi đã không thay đổi lớp theo cách khiến nó không tương thích. Vì vậy, tôi giả định rằng nó là đủ để xác định serialVersionUID trong lớp khi nó được lưu trữ trong dữ liệu đối tượng. Để làm được điều này, tôi cần đọc số serialVersionUID từ dữ liệu được tuần tự hóa.

+0

Điều gì sẽ xảy ra trong trường hợp phương pháp được thêm vào lớp học? Đối tượng tuần tự hóa cũ hơn có thể được đọc bằng cách sử dụng lớp được tuần tự đã sửa đổi không? – sprezzatura

+0

Phương thức không cấu thành trạng thái của một đối tượng, do đó không có vấn đề gì khi đọc đối tượng được tuần tự hóa trừ khi bạn không sử dụng bất kỳ serialVersionUID nào .. –

Trả lời

12

Bạn có thể làm điều này bằng cách mở rộng ObjectInputStream:

public class PrintUIDs extends ObjectInputStream { 

    public PrintUIDs(InputStream in) throws IOException { 
    super(in); 
    } 

    @Override 
    protected ObjectStreamClass readClassDescriptor() throws IOException, 
     ClassNotFoundException { 
    ObjectStreamClass descriptor = super.readClassDescriptor(); 
    System.out.println("name=" + descriptor.getName()); 
    System.out.println("serialVersionUID=" + descriptor.getSerialVersionUID()); 
    return descriptor; 
    } 

    public static void main(String[] args) throws IOException, 
     ClassNotFoundException { 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    ObjectOutputStream oos = new ObjectOutputStream(baos); 
    List<Object> list = Arrays.asList((Object) new Date(), UUID.randomUUID()); 
    oos.writeObject(list); 
    oos.close(); 
    InputStream in = new ByteArrayInputStream(baos.toByteArray()); 
    ObjectInputStream ois = new PrintUIDs(in); 
    ois.readObject(); 
    } 

} 

tôi tin rằng nó sẽ có thể đọc tất cả các dữ liệu tuần tự bằng cách thay thế các mô tả được trả về bởi phương pháp này, nhưng tôi đã không thử nó.

0

Đó chính xác là những gì bạn nên làm - chỉ định số static final long serialVersionUID của riêng bạn.

Có một phần về tài liệu trong tài liệu cho Serializable.

Trừ khi bạn đã chỉ định serialVersionUID Tôi không tin rằng có một cách dễ dàng để giải mã nó ngoài giải mã luồng như @WMR đề xuất.

+0

Lưu ý rằng nó phải được đặt tên là serialVersionUID (không: serialversionuid - Java phân biệt chữ hoa chữ thường) và nên được tư nhân tĩnh cuối cùng dài). – Jesper

+0

Tôi đồng ý. Nhưng có cách nào để đọc uid được tạo ra từ dữ liệu được tuần tự hóa không? – paweloque

5

Có siêu dữ liệu được liên kết với các bit được tuần tự hóa (tiêu đề nếu bạn muốn). Bạn có thể đọc giá trị từ siêu dữ liệu nếu bạn biết vị trí của nó (số SerialVersionUID được viết ở đó cùng với các thông tin khác như tên lớp).

Tôi nghĩ rằng bài viết này có thể giúp bạn: The Java serialization algorithm revealed.

Lưu ý rằng các bit được viết "rõ ràng" (trừ khi bạn mã hóa luồng một cách rõ ràng) để trình chỉnh sửa HEX có thể là tất cả những gì bạn cần để xem số SerialVersionUID là gì.

21

Có một cách dễ dàng để tìm hiểu serialVersionUID của một class-

Giả sử bạn có lớp mà bạn đã quên đề cập đến serialversionUID-

import java.io.Serializable; 

public class TestSerializable implements Serializable { 

} 

Chỉ cần làm this-

serialver -classpath . TestSerializable 

Bản in này-

static final long serialVersionUID = 5832063776451490808L; 

serialver là một tiện ích mà đến cùng với JDK

+2

Nhưng điều này chỉ hoạt động nếu bạn có phiên bản cũ của lớp TestSerializable. Vấn đề của lewap là anh ta không biết giá trị của serialVersionUID là gì với một phiên bản cũ của lớp của đối tượng mà anh ta đã tuần tự hóa. Nếu anh ta không phải phiên bản cũ của lớp nữa, anh ta không thể dùng serialver để tìm hiểu. – Jesper

+0

đó là điều khiển phiên bản dành cho. – james

13

này làm việc cho tôi:

long serialVersionUID = ObjectStreamClass.lookup(YourObject.getClass()).getSerialVersionUID(); 

Hy vọng nó giúp bạn quá.

0

có cách đơn giản hơn nhiều để có được những serialVersionUID của đối tượng serialized - chỉ deserialize nó với commons apache utils serialization để cùng lớp với phiên bản nối tiếp khác nhau uid và đọc thông điệp ngoại lệ mà sẽ được nhiều hơn hoặc ít hơn:

org.apache.commons.lang.SerializationException: java.io.InvalidClassException: my.example.SerializableClass; lớp địa phương không tương thích: dòng classdesc serialVersionUID = -1, lớp địa phương serialVersionUID = -2

0

enter image description here cho các nhà phát triển Android,

bạn cũng có thể kích hoạt tính năng kiểm tra tuần tự từ Settings -> Editor -> Kiểm tra -> enable "Serializable lớp mà không có 'serialVersionUID' kiểm tra" đầu tiên, sau đó ALT + ENTER, studio sẽ tạo serialVersionUID cho bạn.