본문 바로가기
Programing/Java

java.io.InvalidClassException

by Tomining 2015. 7. 15.


위 페이지를 번역한 내용입니다.

java.io.InvalidClassException 은 Object Serialization 을 사용하다보면 흔히 접할 수 있는 오류이다. 이 오류는 3가지 주요 원인이 있는데, 이는 다음과 같다.

  • 클래스의 Serial 버전이 다른 경우
  • 알 수 없는 데이터 타입을 포함한 경우
  • 기본 생성자가 없는 경우

여기서는 디폴트 생성자가 없는 경우를 살펴보도록 하자.

InvalidClassException 이란?

이름에서도 알 수 있듯이, Serialized 또는 Deserialized 된 객체가 위에서 언급한 3가지 이유 중 하나로 invalid 한 상태가 된다.
이로 인해 Serialized 또는 Deserialized 할 수 없다.
ObjectStreamException 을 상속하고 있는 Exception 이다.

InvalidClassException : no valid constructor 는 언제 발생하나?

InvalidClassException 은 프로그램 내에 상속이 있을 때 발생한다.
상속구조에서 Serialization 은 자식 클래스부터 Serializing 한 뒤 상위(부모) Object 로 이동해서 Serializing 하게되며, non-serializable 한 부모 클래스까지 수행된다.

객체가 Deserialized 될 때, non-serializable 한 부모 클래스부터 시작해서 상속구조를 따라 내려간다.
부모 클래스가 non-serializable 하기 때문에 부모 클래스들의 속성정보들을 기본 생성자를 통해서 가져올 수 있는데, 이를 Stream 으로부터 가져올 수 없기 때문에 발생한다.
이런 정보들은 기본 생성자로부터만 받아올 수 있는데, 기본 생성자가 없다면 객체가 invalid 한 상태가 된다.

예제) InvalidClassException

public class JavaIoInvalidClassException {
public static void main(String[] args) {
Child1
c1 = new Child1("child1");

try {
ObjectOutputStream
out = new ObjectOutputStream(new FileOutputStream("sample.dat"));
out.writeObject(c1);
out.close();

ObjectInputStream
in = new ObjectInputStream(new FileInputStream("sample.dat"));
Parent
p = (Child1) in.readObject();
in.close();
}
catch (Exception e) {
e.printStackTrace();
}
}

}

class Parent {
String
parameterName;

public Parent() {

}

public Parent(String name) {
this.parameterName = name;
}
}

class Child1 extends Parent implements Serializable {
public Child1(String name) {
super(name);
}
}
java.io.InvalidClassException: com.tomining.java_tutorial.exception.Child1; no valid constructor
at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:150)
at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:768)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1775)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at com.tomining.java_tutorial.exception.JavaIoInvalidClassException.main(JavaIoInvalidClassException.java:25)

위 프로그램은 Child1 클래스가 Parent 클래스를 상속하고 있다. Child1 은 Serialzable 하다.
Deserialized 할 때, 부모 클래스의 기본생성자를 찾는데, 부모클래스에는 기본생성자가 존재하지 않기 때문에 Exception 이 발생하는 것이다.


해결책

부모클래스에 기본 생성자를 생성해 주면 된다.

class Parent {
String
parameterName;

public Parent() {

}

public Parent(String name) {
this.parameterName = name;
}
}