JavaRush /Java Blog /Random-KO /Java에서 직렬화가 작동하는 방식
ramhead
레벨 13

Java에서 직렬화가 작동하는 방식

Random-KO 그룹에 게시되었습니다
이 기사에서는 직렬화가 무엇인지, Java에서 직렬화가 어떻게 작동하는지 설명합니다. Java에서 직렬화가 작동하는 방식 - 1

소개

개체 직렬화는 개체가 출력 스트림(예: 외부 파일)을 사용하여 참조하는 다른 개체와 자체의 전체 복사본을 저장하는 기능입니다. 이렇게 하면 나중에 필요할 때 직렬화된(저장된) 복사본에서 개체를 다시 만들 수 있습니다. JDK 1.1에 도입된 새로운 기능인 객체 직렬화는 네트워크를 통한 저장 또는 전송을 위해 그룹이나 개별 객체를 비트스트림이나 바이트 배열로 변환하는 기능을 제공합니다. 그리고 명시된 대로, 주어진 비트 스트림이나 바이트 배열은 Java 객체로 다시 변환될 수 있습니다. 이는 주로 ObjectInputStream및 클래스 덕분에 자동으로 발생합니다 ObjectOutputStream. 프로그래머는 Serializable클래스를 생성할 때 인터페이스를 구현하여 이 기능을 구현하기로 결정할 수 있습니다. 직렬화 프로세스는 개체 마샬링 이라고도 하며 역직렬화는 역마샬링 이라고 합니다 . 직렬화는 개체가 자신의 복사본과 해당 개체가 참조하는 다른 모든 개체를 ObjectOutputStream. 저장된 개체는 JFrame유형에 관계없이 데이터 구조, 다이어그램, 클래스 개체 또는 기타 개체일 수 있습니다. 동시에 직렬화는 개체의 형식에 대한 정보를 저장하므로 나중에 역직렬화할 때 해당 정보를 사용하여 개체의 정확한 형식을 다시 만듭니다. 따라서 직렬화는 다음 기능을 제공합니다.
  • 객체를 저장하는 시스템, 즉 객체의 속성을 외부 파일, 디스크 또는 데이터베이스에 저장하는 시스템입니다.
  • 원격 시술 호출 시스템.
  • 예를 들어 COM, COBRA와 같은 소프트웨어 구성 요소의 개체 배포 시스템입니다.
  • 시간에 따른 변수 데이터의 변화를 식별하는 시스템입니다.
직렬화의 개념을 완전히 이해하려면 다른 두 가지 개념인 개체 지속성과 스레드 지속성을 명확하게 이해해야 합니다. 여기서는 기억하기 위해 각각에 대해 조금 이야기하겠습니다. 이에 대한 완전한 설명을 위해서는 각 개념에 대해 별도의 장이 필요합니다.

스트림:

모든 프로그램은 저장 위치나 파이프에 데이터를 써야 하며, 모든 프로그램은 파이프나 저장 위치에서 데이터를 읽어야 합니다. Java에서는 프로그램이 데이터를 작성하고 프로그램에서 데이터를 읽는 이러한 채널을 Streams( Stream) 라고 합니다 . Java에서 직렬화가 작동하는 방식 - 2
그림 1. 스레드의 그래픽 표현
스트림은 주로 두 가지 유형으로 나뉩니다.
  • *Streams라는 바이트 스트림 클래스
  • *Reader 및 *Writer라는 문자 스트림 클래스
각 데이터 쓰기 스트림에는 쓰기 방법 세트가 포함되어 있습니다. 따라서 각 데이터 읽기 스레드에는 유사한 읽기 방법 세트가 있습니다. 스레드가 생성되면 이러한 메서드를 모두 호출해야 합니다.

고집

객체 지속성은 객체가 살아 있는 능력, 즉 프로그램 실행 후에도 "생존"하는 능력입니다. 즉, 런타임 시 생성된 모든 객체는 해당 객체가 더 이상 사용되지 않을 때마다 JVM 스캐빈저에 의해 삭제됩니다. 그러나 지속성 API가 구현되면 이러한 객체는 JVM 스캐빈저에 의해 삭제되지 않고 대신 "살아 있는" 상태가 허용되므로 다음에 애플리케이션을 시작할 때 해당 객체에 액세스할 수도 있습니다. 즉, 지속성은 실행 중인 애플리케이션의 수명과 관계없이 객체에 수명이 있음을 의미합니다. 지속성을 구현하는 한 가지 방법은 외부 파일이나 데이터베이스 어딘가에 개체를 저장한 다음 나중에 해당 파일이나 데이터베이스를 소스로 사용하여 개체를 복원하는 것입니다. 여기서 직렬화가 시작됩니다. JVM이 실행되는 동안에는 비지속적 객체가 존재합니다. 직렬화된 객체는 단순히 스트림으로 변환된 객체로, 외부 파일에 저장되거나 저장 및 복구를 위해 네트워크를 통해 전송됩니다.

직렬화 가능 인터페이스 구현

java.io.Serializable모든 클래스는 해당 클래스의 객체를 직렬화하기 위한 인터페이스를 구현해야 합니다 . 인터페이스 Serializable에는 메서드가 없으며 클래스를 직렬화 가능한 것으로 식별할 수 있도록 표시만 합니다. 직렬화된 클래스 객체의 필드만 저장할 수 있습니다. 메서드나 생성자는 직렬화된 스트림의 일부로 저장되지 않습니다. 객체가 다른 객체에 대한 참조 역할을 하는 경우 해당 객체의 클래스가 인터페이스를 구현하면 해당 객체의 필드도 직렬화됩니다 Serializable. 즉, 이렇게 얻은 이 객체의 그래프는 완전히 직렬화 가능합니다. 개체 그래프에는 개체 및 하위 개체 필드의 트리 또는 구조가 포함됩니다. 인터페이스 구현을 돕는 두 가지 주요 클래스 Seriliazable:
  • ObjectInputStream
  • ObjectOutputStream
목록 1. 직렬화를 표시하는 간단한 클래스의 예
import java.io.*;
public class RandomClass implements Serializable {
 // Генерация рандомного значения
 private static int r() {
        return (int)(Math.random() * 10);
 }
    private int data[];
    // Конструктор
public RandomClass() {
        datafile = new int[r()];
        for (int i=0; i<datafile.length; i++)
        datafile[i]=r();
 }
    public void printout() {
 System.out.println("This RandomClass has "+datafile.length+" random integers");
 for (int i=0; i<datafile.length; i++) {
        System.out.print(datafile[i]+":");
        System.out.println();
    }
}
위 코드에서는 직렬화 가능한 클래스가 생성됩니다. 직렬화 인터페이스에 의해 "표시"됩니다. 클래스는 인스턴스가 생성될 때 임의의 정수 배열을 생성합니다. 아래 코드는 ObjectOutputStream. 프로그램에는 정수 배열이 있지만 직렬화를 위해 내부 개체를 반복할 필요가 없습니다. 인터페이스는 Seriliazable이를 자동으로 처리합니다. 목록 2. 파일로 출력하기 위해 객체를 직렬화하는 간단한 예
import java.io.*;
import java.util.*;
public class OutSerialize {
    public static void main (String args[]) throws IOException {
        RandomClass rc1 = new RandomClass();
        RandomClass rc2 = new RandomClass();
//создание цепи потоков с потоком вывода an object в конце
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("objects.dat"));
        Date now = new Date(System.currentTimeMillis());
//java.util.* был импортирован для использования класса Date
        out.writeObject(now);
        out.writeObject(rc1);
        out.writeObject(rc2);
out.close();
        System.out.println("I have written:");
System.out.println("A Date object: "+now);
        System.out.println("Two Group of randoms");
rc1.printout();
rc2.printout();
 }
}
아래 코드는 ObjectInputStream외부 파일에서 직렬화된 데이터를 프로그램으로 읽는 클래스의 기능을 보여줍니다. 객체는 파일에 기록된 순서와 동일한 순서로 읽혀집니다. 목록 3. 직렬화된 객체 읽기 또는 역직렬화
import java.io.*;
import java.util.*;
public class InSerialize {
 public static void main (String args[]) throws  IOException, ClassNotFoundException {
    ObjectInputStream in =  new ObjectInputStream (new FileInputStream("objects.dat"));
 Date d1 = (Date)in.readObject();
 RandomClass rc1 = (RandomClass)in.readObject();
    RandomClass rc2 = (RandomClass)in.readObject();
    System.out.println("I have read:");
    System.out.println("A Date object: "+d1);
    System.out.println("Two Group of randoms");
    rc1.printout();
rc2.printout();
 }
}
AWT 클래스를 포함하여 거의 모든 Java 클래스를 직렬화할 수 있습니다. 창인 프레임에는 일련의 그래픽 구성 요소가 포함되어 있습니다. 프레임이 직렬화되면 직렬화 엔진이 이를 처리하고 프레임의 모든 구성 요소와 데이터(위치, 콘텐츠 등)를 직렬화합니다. 일부 Java 클래스 개체에는 임시 운영 체제 리소스를 참조하는 데이터가 포함되어 있으므로 직렬화할 수 없습니다. 예를 들어 클래스 java.io.FileInputStreamjava.lang.Thread. 객체에 직렬화 가능하지 않은 요소에 대한 참조가 포함되어 있으면 전체 직렬화 작업이 실패하고 예외가 발생합니다 NotSerializableException. 직렬화되지 않은 객체의 참조를 참조하는 객체가 있으면 temporary 키워드를 사용하여 직렬화할 수 있습니다 . 목록 4. Transient 키워드를 사용하여 직렬화 가능한 개체 만들기
public class Sclass implements Serializable{
public transient Thread newThread;
//помните, что поток(поток параллельного исполнения) по умолчанию не сериализуемый класс
    private String studentID;
    private int sum;
}

직렬화 보안

Java에서 클래스를 직렬화하려면 해당 클래스의 모든 데이터를 스트림을 통해 외부 파일이나 데이터베이스로 전달해야 합니다. 원할 때마다 직렬화되는 데이터를 제한할 수 있습니다. 이를 수행하는 방법에는 두 가지가 있습니다.
  • 임시로 선언된 각 클래스 매개변수는 직렬화되지 않습니다. (기본적으로 모든 클래스 매개변수는 직렬화됩니다.)
  • 또는 직렬화하려는 클래스의 각 매개변수는 태그로 표시됩니다 Externalizable(기본적으로 매개변수는 직렬화되지 않습니다).
해당 객체의 데이터 필드가 temporaryObjectOutputStream 로 표시된 경우 객체에 대해 호출될 때 데이터 필드는 으로 직렬화되지 않습니다 . 예를 들어: . 반면에 객체의 데이터를 직렬화 가능으로 명시적으로 선언하려면 클래스가 해당 객체의 데이터를 명시적 으로 쓰고 읽는 것으로 표시해야 합니다. private transient String passwordExternalizablewriteExternalreadExteranl

결론

객체 직렬화 기능은 많은 분산 시스템에서 데이터를 전송하는 방법으로 사용됩니다. 그러나 직렬화는 숨겨진 세부 사항을 드러내므로 추상 데이터 유형의 신뢰성을 파괴하고 결과적으로 캡슐화를 파괴합니다. 동시에 직렬화된 개체의 데이터가 원본 개체에 있던 데이터와 동일하다는 것을 아는 것이 좋습니다. 이는 여러 줄의 코드가 사용되더라도 인터페이스를 구현 ObjectInputValidation하고 메서드를 재정의할 수 있는 좋은 기회이기도 합니다. validateObject()객체를 찾을 수 없으면 적절하게 예외를 던질 수 있습니다 InvalidObjectException. 원본 기사: Java에서 직렬화가 작동하는 방식
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION