JAVA

자바 직렬화(Serialization)

icedstone 2025. 3. 9. 15:07
반응형

직렬화: 객체를 스트림으로 변환하는 것

역직렬화: 스트림을 객체로 변환하는 것

 

serialVersionUID

JVM은 직렬화와 역직렬화를 하는 시점의 클래스에 대한 버전 번호를 부여합니다.

만약 그 시점에 클래스의 정의가 바뀌어 있다면 새로운 버전 번호를 할당합니다.

그래서 직렬화 할 때의 버전 번호와 역직렬화를 할 때의 버전 번호가 다르면 역직렬화가 불가능하게 될 수도 있습니다. 이런 문제를 해결하려면 개발자가 직접 버전 번호를 정해주면 됩니다.

 

class 정보가 변경되어도 같은 class로 인식하기를 원한다면 serialVersionUID를 선언해주면 된다.


만약에 아래 상황을 살펴보자

public class TestClass implements Serializable {
  String test1;
}

//생성자나 기타 소스는 생략할게요
public class Main {
  public static void main(String[] args) {
    TestClass testClass = new TestClass("1");
    byte[] data = covertToByte(testClass);
    
    writeFile(data)
  }
}

//byte[] convertToByte(Object object)
//void writeFile(byte[] data)
//기타 method는 생략할게요

 

TestClass를 수정하게 되어서 다음과 같이 수정했다.

public class TestClass implements Serializable {
  String test1;
  String test2;
}

 

이 상황에서

public class Main {
  public static void main(String[] args) {
    byte[] data = readFile();
    TestClass testClass = (TestClass) convertToObject(data);
  }
}

//byte[] readFile()
//Object convertToObject(byte[] data)

 

를 하게 된다면 다음과 같은 오류가 발생한다.

java.io.InvalidClassException: Main$TestClass; local class incompatible: stream classdesc serialVersionUID = 4560265494419914312, local class serialVersionUID = -1723379655482829338

 

만약 serialVersionUID가 있었다면 어떻게 되었을까?

 

public class TestClass implements Serializable {
  private static final long serialVersionUID = 1L;
  String test1;
  String test2;
}
public class Main {
  public static void main(String[] args) {
    byte[] data = readFile();
    TestClass testClass = (TestClass) convertToObject(data);
    System.out.println(testClass);
  }
}

 

결과는 TestClass{test1='1', test2='null'} 로 역직렬화가 된 것을 확인할 수 있다.

 

반응형

 

참고

transient: 직렬화에서 제외시켜주는 예약어

static: 자동적으로 직렬화 대상에서 제외된다.

반응형