Avatar
1
Vu Luong Anh Pundit
serialVersionUID trong class java để làm gì?
Em đọc code hay thấy có trường serialVersionUID ở đầu các class trong java. Cái biến này để làm gì và khi nào thì nên dùng nó vậy anh?
  • Answer
Remain: 5
2 Answers
Avatar
hovanvydut Pundit
Em chấm hóng đợi câu trả lời của anh Dũng ạ. Em chỉ biết khi nào cần ghi object ra bytes thì em phải implements Serializeable, để sau này đọc bytes đó --> object ra lại như trước. Hoặc là các object từ server gửi về client cũng phải implements Serializable
  • 0
  • Reply
Avatar
tvd12 Pundit
tvd12 Pundit
The Best Answer
Đây là một trong những cái lịch sử lâu đời của Java, và giờ anh cũng không biết nó còn dùng để làm gì nữa không. Giờ hãy nói kỹ về nó nhé.

  1. Nguyên nhân ra đời

Ngày xưa chưa có sự ra đời của protobuf hay message pack, hay json, xml như ngày nay, mà khi gửi nhận qua mạng hay lưu dữ liệu thì phải biến object thành byte array đúng không nhỉ? Vậy thì ông Java phải viết riêng thư viện serialize và deserialize cho mình rồi. Tuy nhiên lại có vấn đề thế này:

Chúng ta có 2 lớp giống hệt nhau về tên gói, tên lớp và serialVersionUID kiểu:

// đây là lớp của chúng ta
class A implements Serializable {
    private static final long serialVersionUID = 2L;
    String name;
    String value;
}

// đây là lớp của hacker đã xoá mất trường name để nhằm mục tiêu chiếm đoạt giá trị value
class A implements Serializable {
    private static final long serialVersionUID = 2L;
    String value;
}

Rõ ràng là khi hacker dùng đoạn code này:

ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteOut);
A a = new A();
a.value = "Hello";
out.writeObject(a);
byte[] bytes = byteOut.toByteArray();

Kết quả sẽ là 1 byte array: [-84, -19, 0, 5, 115, 114, 0, 52, 99, 111, 109, 46, 116, 118, 100, 49, 50, 46, 101, 120, 97, 109, 112, 108, 101, 46, 115, 101, 114, 105, 97, 108, 105, 122, 101, 114, 46, 74, 97, 118, 97, 83, 101, 114, 105, 97, 108, 105, 122, 101, 114, 69, 120, 97, 109, 112, 108, 101, 36, 65, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 1, 76, 0, 5, 118, 97, 108, 117, 101, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 120, 112, 116, 0, 5, 72, 101, 108, 108, 111]

Và gửi cái mảng byte này đến rmi server, rmi server sẽ deserialize kiểu này:

ByteArrayInputStream byteIn = new ByteArrayInputStream(bytes);
ObjectInputStream in = new ObjectInputStream(byteIn);

A a = (A)in.readObject();

thì bản thân rmi server sẽ không thể biết được là dữ liệu byte array kia là do ai gửi, đến từ đâu, vì cùng lớp, cùng serialVersionUID nên server sẽ chấp nhận dữ liệu của hacker. Vậy nên phải sinh ra serialVersionUID khác nhau để thêm 1 bước nữa kiểm tra tính hợp lệ của dữ liệu. Trong trường hợp này, nếu lớp của hacker là:

 public static class A implements Serializable {
        private static final long serialVersionUID = 3L;

        public String value;
}

Thì kết quả ở trên server sẽ là:

Exception in thread "main" java.io.InvalidClassException: com.tvd12.example.serializer.JavaSerializerExample$A; local class incompatible: stream classdesc serialVersionUID = 2, local class serialVersionUID = 3
	at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2001)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1848)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2158)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1665)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:501)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:459)
	at com.tvd12.example.serializer.JavaSerializerExample.main(JavaSerializerExample.java:26)

  1. Ứng dụng ngày nay

Ngày nay thi chúng ta có các thư viện serialize + package message khủng hơn rất nhiều rồi như protobuf, message pack, mà cũng không còn nhiều người dùng đến rmi hay các server của java nữa, nên em có thể bỏ qua nó cũng được, nếu có exception thì thêm vào cũng không sao

  • 2
  • Reply
Dã man con ngang !  –  jungtin 1630230392000