JAVA 직렬화란?
JAVA시스템 내부에서 사용되는 데이터나 객체들을 외부 자바 시스템에서도 사용할 수 있도록 byte형태로 변환하는 기술로 바이트로 변환된 데이터를 다시 객체로 변환하는 역직렬화도 포함된다.
대부분 OS 프로세스를 구현할 때 서로 다른 가상 메모리공간에 있는 Object type의 참조값 데이터 인스턴스는 전달 할 수 없다.
전달한다고 해도 서로 다른 메모리 공간에서는 무의미하다.
서로 다른 memory공간사이에서 데이터를 전달할 때 주소값이 아닌 직렬화된 객체 데이터를 이용할 수 있다.(이것이 직렬화)
JAVA시스템간에 존재하는 것으로 Data type이 자동으로 맞춰진다.
example)
JAVA안에서 객체 안에 객체가 존재할 수 있는데 Parent객체 안에 Child객체가 있을 때 Child객체가 메모리에 올라가면 참조할 수 있는 주소값이 생긴다. 이를 직렬화할 경우 주소값이 아닌 Child 데이터 자체를 Primitive Type의 byte로 변환한다.
직렬화된 데이터를 파일을 저장하거나 네트워크 전송할 때 파싱하여 사용할 수 있다.
직렬화를 사용하는 이유
JVM 메모리에 상주되어있는 객체 데이터를 그대로 영속화할 때 사용한다.
시스템이 종료되어도 사라지지 않는 데이터로 네트워크 전송이 가능하다.
- 서블릿 세션에서 사용한다. 서블릿 메모리 위에서만 존재한다면 필요없고 파일 저장 혹은 클러스터링, DB저장 옵션을 선택하면 세션자체가 직렬화된 후 저장되어 전달된다.
- 캐시직렬화. DB조회한 데이터가 실시간으로 변경되는 경우가 아니면 메모리나 파일 등의 저장소에 저장한 후 동일한 요청이 오면 저장된 객체를 응답한다. 캐시를 이용하면 DB리소스를 절약할 수 있다.
serialVersionUID 사용하는 방법
JAVA 직렬화 & 역직렬화할 때 사용하는 버전 정보다.
해당 버전을 명시하지 않으면 직렬화, 역직렬화할 때 자바 컴파일러가 임의로 버전을 지정하여 직렬화한다.
그럴 경우 역직렬화가 되지 않기 때문에 동일한 serialVersionUID를 지정하면 에러없이 직렬화가 가능하다.
그러나 클래스에 멤버변수 타입을 변경할 경우 에러가 발생한다.
멤버 변수의 제거나 이름 변경은 데이터 누락이 발생한다.
예외가 생길 수 있기 때문에 예외처리가 필요하다.
public class Test implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
public Test(String name) {
this.name = name;
}
}
Test test = new Test("hi");
String result = Base64.getEncoder().encodeToString(toSerialize(test));
System.out.println(result);
byte[] decode = Base64.getDecoder().decode(result);
ObjectMapper objectMapper =new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
Object obj = toDeserialize(decode);
Test t = (Test) obj;
String json = objectMapper.writeValueAsString(t);
System.out.println(json);
public <T> byte[] toSerialize(T obj) {
byte[] serialized;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(obj);
serialized = baos.toByteArray();
return serialized;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public <T> Object toDeserialize(byte[] serialized) throws IOException {
try (ByteArrayInputStream bais = new ByteArrayInputStream(serialized)) {
try (ObjectInputStream ois = new ObjectInputStream(bais)) {
// 역직렬화된 객체를 읽어온다.
Object objectMember = ois.readObject();
return objectMember;
} catch (UnsupportedEncodingException | ClassNotFoundException e) {
e.printStackTrace();
}
}
return null;
}
'Java' 카테고리의 다른 글
JAVA GC가 발생하는 시기(Garbage Collector) (0) | 2022.02.10 |
---|---|
JAVA enum vs static 비교 (0) | 2022.02.07 |
java static 사용이유 생성자 대신 static 팩토리 메소드 (0) | 2021.12.18 |
JAVA Optional (0) | 2021.02.03 |
JAVA Stream API 란? (0) | 2021.02.02 |