>  기사  >  Java  >  일반적인 Java 직렬화 오류는 무엇입니까?

일반적인 Java 직렬화 오류는 무엇입니까?

王林
王林원래의
2024-04-16 18:18:01766검색

일반적인 Java 직렬화 오류는 다음과 같습니다. 클래스 버전 충돌(InvalidClassException) 직렬화 가능한 슈퍼클래스 또는 인터페이스가 선언되지 않음(NotSerializedException) 액세스 거부 또는 불법 반영 직렬화된 객체(IllegalAccessException) 정적 필드의 직렬화가 변경 가능하거나 순환적임 참조(StackOverflowException 또는 일관성 없는 상태)

일반적인 Java 직렬화 오류는 무엇입니까?

일반적인 Java 직렬화 오류

Java 직렬화 오류: 객체를 바이너리 스트림으로 변환하거나 바이너리 스트림에서 객체를 재구성할 때 발생하는 오류입니다. 일반적으로 다음과 같은 이유로 발생합니다.

1. 클래스 버전 충돌

  • 직렬화해야 하는 개체는 개체를 재구성할 때 클래스 버전과 호환되어야 합니다. 호환되지 않으면 InvalidClassException 오류가 발생합니다. InvalidClassException 错误。
class MyClass implements Serializable {
    private static final long serialVersionUID = 1L;

    private String name;

    // 省略其他代码...
}

// 序列化对象后修改了 MyClass
MyClass myObject = new MyClass();
myObject.setName("John Doe");

// 将对象序列化到文件
FileOutputStream fos = new FileOutputStream("object.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(myObject);
oos.close();

// 更改 MyClass 的 serialVersionUID
MyClass.serialVersionUID = 2L;

// 从文件中读取并反序列化对象
FileInputStream fis = new FileInputStream("object.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
MyClass deserializedObject = (MyClass) ois.readObject();
ois.close();

2. 未声明可序列化的超类或接口

  • 任何可序列化的子类都必须声明其直接超级类或实现的接口也具有可序列化性。否则,它会导致 NotSerializableException
class NotSerializable {
    // ...
}

class MyClass extends NotSerializable implements Serializable {
    // ...
}

3. 拒绝访问或非法反射

  • 序列化的对象必须具有带有 private 访问修饰符的 writeObjectreadObject 方法。反射访问这些方法会导致 IllegalAccessException
class MyClass implements Serializable {
    private void writeObject(ObjectOutputStream oos) throws IOException {
        // ...
    }

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        // ...
    }
}

// 使用反射调用 writeObject
ObjectOutputStream oos = new ObjectOutputStream(new ByteArrayOutputStream());
oos.writeObject(myObject);
Method m = MyClass.class.getDeclaredMethod("writeObject", ObjectOutputStream.class);
m.setAccessible(true);
m.invoke(myObject, oos);

4. 静态字段的序列化

  • 静态字段不会序列化。如果要序列化它们,请将其声明为瞬态(transient)。
class MyClass implements Serializable {
    private static String staticField;
    
    private String instanceField;

    // ...
}

5. 可变或循环引用

  • 循环引用会导致 StackOverflowException
  • // 可变对象
    class MyClass implements Serializable {
        private int mutableField;
        
        // ...
    }
    
    // 循环引用
    class MyClass1 implements Serializable {
        private MyClass myClass2;
    
        class MyClass2 implements Serializable {
            private MyClass1 myClass1;
        }
    }
🎜2. 직렬화 가능한 슈퍼클래스나 인터페이스가 선언되지 않았습니다.🎜🎜🎜🎜모든 직렬화 가능한 하위 클래스는 직계 슈퍼클래스나 구현된 인터페이스도 직렬화 가능하다고 선언해야 합니다. 그렇지 않으면 NotSerializedException이 발생합니다. 🎜🎜rrreee🎜🎜3. 액세스 거부 또는 불법 반사 🎜🎜🎜🎜직렬화된 객체에는 private 액세스 수정자 /code> 메서드와 함께 writeObjectreadObjectIllegalAccessException을 발생시킵니다. 🎜🎜rrreee🎜🎜4. 정적 필드 직렬화🎜🎜🎜🎜정적 필드는 직렬화되지 않습니다. 직렬화하려면 일시적(transient)으로 선언하세요. 🎜🎜rrreee🎜🎜5. 변경 가능 또는 순환 참조 🎜🎜🎜🎜순환 참조는 StackOverflowException을 일으킬 수 있습니다. 변경 가능한 객체는 일관성 없는 상태로 이어질 수 있습니다. 🎜🎜rrreee

위 내용은 일반적인 Java 직렬화 오류는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.