자바 serializable 깊이 이해

11046 단어 자바Serializable
1.직렬 화 된 개념 과 목적 
1.Serialization 이란 무엇 인가?
직렬 화(Serialization)는 컴퓨터 과학 의 한 개념 으로 대상 을 미디어(예 를 들 어 파일,내 적 버퍼 등)에 저장 하거나 이 진 방식 으로 네트워크 를 통 해 전송 하 는 것 을 말한다.이후 이 연속 적 인 자릿수 에서 원 초적 인 대상 과 같은 상 태 를 가 진 대상 을 반전 행 화 를 통 해 재 구축 할 수 있 기 때문에 특정 상황 에서 도 사본 을 얻 었 다 고 할 수 있 지만 모든 상황 이 다 그런 것 은 아니다.
자바 에는 Serialization API 가 개발 자 에 게 표준 메커니즘 을 제공 하여 직렬 화 클래스 를 제공 합 니 다.
2.Serilzation 은 왜?
특히 직렬 화 는 주로 세 가지 용도 가 있다.
1)지구 화 메커니즘 으로서
 
 
 
 FileOutputStream 스 트림 방식 을 사용 하면 데이터 가 자동 으로 파일 에 기 록 됩 니 다.
2)복제 메커니즘 으로서
 
 
 
 하면,만약,만약...ByteArrayOutputStream
흐 르 는 방식 으로 데 이 터 는 메모리 에 있 는 바이트 배열 에 기 록 됩 니 다.이 바이트 배열 은 초기 대상 의 복사 본 을 만 드 는 데 사용 할 수 있 습 니 다.
3)일종 의 통신 메커니즘 으로서
 
 
 
 소켓(Socket)스 트림 을 사용 하 는 방식 이 라면 데 이 터 는 자동 으로 네트워크 연결 을 통 해 다른 점 을 전송 하고 이 점 의 프로그램 이 무엇 을 할 지 결정 합 니 다.
2.직렬 화 방법 
            JDK 1.1 부터 자바 언어 는 대상 직렬 화 체 제 를 제공 합 니 다.자바.io 패키지 에서 인터페이스 Serialization 은 대상 직렬 화 를 실현 하 는 도구 로 사용 되 며,Serialization 클래스 의 대상 만 직렬 화 할 수 있 습 니 다. 
            Serializable 인터페이스 에는 아무런 방법 이 없습니다.Serializable 인 터 페 이 스 를 실현 하려 면 직렬 화 프로 토 콜 에 참여 하 는 것 이지 특별한 방법 이 필요 하지 않다 는 것 을 나타 낸다.다음은 대상 을 직렬 화 하 는 방법 을 실례 를 통 해 소개 한다. 
1.직렬 화 대상 정의 
            대상 을 직렬 화 하려 면 Serializable 인 터 페 이 스 를 실현 해 야 합 니 다.우 리 는 클래스 Student 를 다음 과 같이 정의 합 니 다.
import java.io.Serializable;   
  
public class Student implements Serializable {   
  
    int id;//      
  
    String name;//      
  
    int age;//      
  
    String department; //      
  
    public Student(int id, String name, int age, String department) {   
  
        this.id = id;   
  
        this.name = name;   
  
        this.age = age;   
  
        this.department = department;   
  
    }   
  
}  

2.구조 대상 의 입 출력 흐름 
            대상 을 직렬 화 하려 면 일정한 대상 의 출력/입력 흐름 과 연결 되 어야 하 며,대상 의 출력 흐름 을 통 해 대상 상 태 를 저장 한 다음 대상 의 입력 흐름 을 통 해 대상 상 태 를 회복 해 야 합 니 다. 
            java.io 패키지 에 서 는 Object InputStream 과 Object OutputStream 을 제공 하여 데이터 흐름 기능 을 읽 기 가능 한 대상 으로 확장 합 니 다.Object InputStream 에 서 는 readObject()방법 으로 대상 을 직접 읽 을 수 있 으 며,Object OutputStream 에 서 는 writeObject()방법 으로 대상 을 출력 흐름 에 직접 저장 할 수 있 습 니 다.
import java.io.FileInputStream;   
import java.io.FileOutputStream;   
import java.io.IOException;   
import java.io.ObjectInputStream;   
import java.io.ObjectOutputStream;   
  
public class ObjectSer {   
  
    public static void main(String args[]) throws IOException,   
            ClassNotFoundException {   
  
        Student stu = new Student(981036, "LiuMing", 18, "CSD");   
  
        FileOutputStream fo = new FileOutputStream("data.ser");   
  
        ObjectOutputStream so = new ObjectOutputStream(fo);   
  
        try {   
  
            so.writeObject(stu);   
  
            so.close();   
  
        } catch (IOException e) {   
            System.out.println(e);   
        }   
  
        stu = null;   
  
        FileInputStream fi = new FileInputStream("data.ser");   
  
        ObjectInputStream si = new ObjectInputStream(fi);   
  
        try {   
  
            stu = (Student) si.readObject();   
  
            si.close();   
  
        } catch (IOException e)   
  
        {   
            System.out.println(e);   
        }   
  
        System.out.println("Student Info:");   
  
        System.out.println("ID:" + stu.id);   
  
        System.out.println("Name:" + stu.name);   
  
        System.out.println("Age:" + stu.age);   
  
        System.out.println("Dep:" + stu.department);   
  
    }   
  
}  
      :

        Student Info: 

  ID:981036 

  Name:LiuMing 

  Age:18 

  Dep:CSD
 이 예 에서 우 리 는 먼저 하나의 Student 를 정의 하여 Serializable 인 터 페 이 스 를 실현 한 다음 에 대상 이 출력 하 는 writeObject()방법 을 통 해 Student 대상 을 파일 data.ser 에 저장 합 니 다.이후 집 입력 흐름 에 대한 readObjcet()방법 으로 파일 data.ser 에서 저 장 된 Student 대상 을 읽 습 니 다.실행 결 과 를 보면 직렬 화 메커니즘 을 통 해 대상 의 상 태 를 정확하게 저장 하고 복구 할 수 있다. 
3.직렬 화 된 주의사항 
1.저장 할 수 있 는 요소 직렬 화 
            직렬 화 는 대상 의 비 정적 구성원 교 체 량 만 저장 할 수 있 고 그 어떠한 구성원 방법 과 정적 구성원 변 수 를 저장 할 수 없 으 며 직렬 화 는 변수의 값 만 저장 할 수 있 으 며 변수의 어떠한 수정자 도 저장 할 수 없습니다. 
2.transient 키워드 
            어떤 유형의 대상 에 대해 서 는 그 상 태 는 순간 적 이 며,이러한 대상 은 그 상 태 를 저장 할 수 없다.예 를 들 어 Thread 대상 이나 FileInputStream 대상 은 이 필드 에 대해 transient 키워드 로 표시 해 야 합 니 다.그렇지 않 으 면 컴 파일 러 가 조 치 를 취 할 것 입 니 다. 
            또한 직렬 화 는 대상 을 디스크 에 저장 하거나 네트워크 에 발달 한 데이터 와 관련 될 수 있 으 며 이 럴 때 안전 문제 가 발생 할 수 있다.데 이 터 는 자바 운영 환경 외 에 자바 보안 메커니즘 의 제어 에 있 지 않 기 때문이다.보안 이 필요 한 필드 는 영구적 인 미디어 에 저장 하거나 간단하게 처리 하지 않 고 저장 해 서 는 안 되 며 안전성 을 확보 하기 위해 서 입 니 다.이 필드 에 transient 키 워드 를 추가 해 야 합 니 다.
다음은 자바 규범 에서 transient 키워드 에 대한 설명 입 니 다.  
      The   transient   marker   is   not   fully   specified   by   The   Java   Language     Specification   but   is   used   in   object   serialization   to   mark   member   variables   that   should   not   be   serialized.
 다음은 transient 의 응용 예 입 니 다.
//LoggingInfo.java
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;
public class LoggingInfo implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private Date loggingDate = new Date();
private String uid;
private transient String pwd;
LoggingInfo(String user, String password) {
uid = user;
pwd = password;
}
public String toString() {
String password = null;
if (pwd == null) {
password = "NOT SET";
} else {
password = pwd;
}
return "logon info: 
" + "user: " + uid + "
logging date : " + loggingDate.toString() + "
password: " + password; } public static void main(String[] args) { LoggingInfo logInfo = new LoggingInfo("MIKE", "MECHANICS"); System.out.println(logInfo.toString()); try { ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream( "logInfo.out")); o.writeObject(logInfo); o.close(); } catch (Exception e) {// deal with exception } // To read the object back, we can write try { ObjectInputStream in = new ObjectInputStream(new FileInputStream( "logInfo.out")); LoggingInfo logInfo1 = (LoggingInfo) in.readObject(); System.out.println(logInfo1.toString()); } catch (Exception e) {// deal with exception } } }

요약:
서열 화 는 두 부분 으로 나 뉘 는데 그것 이 바로 서열 화 와 반 서열 화 이다.직렬 화 는 이 과정의 첫 번 째 부분 으로 데 이 터 를 바이트 흐름 으로 분해 하여 파일 에 저장 하거나 네트워크 에서 전송 할 수 있 도록 한다.역 직렬 화 는 바이트 흐름 을 열 고 대상 을 재 구성 하 는 것 이다.대상 서열 화 는 기본 데이터 형식 을 바이트 표시 로 바 꿔 야 할 뿐만 아니 라 데이터 복원 도 해 야 한다.복구 데 이 터 는 복구 대상 인 스 턴 스 가 있어 야 합 니 다.Object OutputStream 의 직렬 화 과정 은 대상 유형 과 버 전 정 보 를 포함 하여 바이트 흐름 과 연 결 됩 니 다.역 직렬 화 시 JVM 은 헤더 정보 로 대상 인 스 턴 스 를 생 성 한 다음 대상 바이트 흐름 의 데 이 터 를 대상 데이터 구성원 에 복사 합 니 다.
직렬 화 과정 은 대상 이 바이트 흐름 을 기록 하고 바이트 흐름 에서 대상 을 읽 는 것 이다.대상 상 태 를 바이트 흐름 으로 변환 한 후 자바.io 패키지 의 각종 바이트 흐름 류 로 파일 에 저장 하고 다른 스 레 드 로 파이프 하거나 네트워크 연결 을 통 해 대상 데 이 터 를 다른 호스트 로 보 낼 수 있 습 니 다.대상 의 서열 화 기능 은 매우 간단 하고 강력 하 며 RMI,Socket,JMS,EJB 에서 모두 응용 된다.대상 서열 화 문 제 는 인터넷 프로 그래 밍 에서 가장 감동적인 과제 가 아니 지만 상당히 중요 하고 많은 실 용적 의 미 를 가진다.
대상 의 서열 화 는 분포 식 대상 을 실현 할 수 있다.주요 응용 예:RMI 는 대상 을 이용 하여 원 격 호스트 의 서 비 스 를 직렬 화 하려 고 합 니 다.로 컬 컴퓨터 에서 대상 을 실행 할 때 와 같 습 니 다.
자바 대상 의 직렬 화 는 한 대상 의 데 이 터 를 보존 할 뿐만 아니 라 대상 이 인용 한 모든 대상 의 데 이 터 를 재 귀적 으로 저장 합 니 다.전체 대상 차원 을 바이트 흐름 에 기록 할 수 있 으 며 파일 에 저장 하거나 네트워크 연결 에 전달 할 수 있 습 니 다.대상 의 직렬 화 를 이용 하여 대상 의'딥 복사',즉 대상 자체 와 인용 대상 자 체 를 복제 할 수 있다.대상 을 서열 화하 면 전체 대상 서열 을 얻 을 수 있다.
마지막 으로 자주 만 나 는 진실 한 상황 을 열거 했다.그들 은 자바 직렬 화 와 관련 되 고 상황 이 나타 난 원인 을 분석 함으로써 독자 들 로 하여 금 자바 직렬 화 중의 일부 고급 인식 을 쉽게 기억 하 게 한다.

질문
상황:두 클 라 이언 트 A 와 B 는 네트워크 를 통 해 대상 데 이 터 를 전달 하려 고 합 니 다.A 단 은 대상 C 를 바 이 너 리 데이터 로 정렬 하여 B 에 게 전달 하고 B 는 역 직렬 화 를 통 해 C 를 얻 습 니 다.
문제:C 대상 의 모든 경 로 는 come.inout.Test 라 고 가정 합 니 다.A 와 B 단 에 이런 종류의 파일 이 있 고 기능 코드 가 완전히 일치 합 니 다.Serializable 인 터 페 이 스 를 실 현 했 지만 반 서열 화 할 때 항상 알림 이 성공 하지 못 했다.
해결:가상 컴퓨터 가 역 직렬 화 를 허용 하 는 지 여 부 는 클래스 경로 와 기능 코드 가 일치 하 는 지 에 달 려 있 을 뿐만 아니 라 매우 중요 한 것 은 두 가지 유형의 직렬 화 ID 가 일치 하 는 지 여부 입 니 다(즉,private static final long serial VersionUID=1L).두 단락 의 같은 코드 중 두 종류의 기능 코드 가 완전히 일치 하지만 서열 화 된 ID 가 다 르 기 때문에 그들 은 서로 서열 화 되 고 반 서열 화 될 수 없다.
직렬 화 ID 는 Eclipse 에서 두 가지 생 성 정책 을 제공 합 니 다.하 나 는 고정된 1L 이 고 하 나 는 중복 되 지 않 는 log 형식의 데 이 터 를 무 작위 로 생 성 하 는 것 입 니 다(실제로 JDK 도 구 를 사용 하여 생 성).여기 서 특별한 수요 가 없 으 면 기본 1L 로 코드 가 일치 할 때 반 직렬 화 에 성공 할 수 있 도록 하 는 것 이 좋 습 니 다.그러면 무 작위 로 생 성 된 직렬 화 ID 는 어떤 역할 을 합 니까?어떤 때 는 직렬 화 ID 를 바 꾸 면 일부 사용자 의 사용 을 제한 할 수 있 습 니 다.
민감 필드 암호 화
상황:서버 에서 클 라 이언 트 에 게 직렬 화 대상 데 이 터 를 보 냅 니 다.대상 중 일부 데 이 터 는 민감 합 니 다.예 를 들 어 암호 문자열 등 이 있 습 니 다.이 암호 필드 를 직렬 화 할 때 암호 화 하려 고 합 니 다.클 라 이언 트 가 복호화 키 를 가지 고 있다 면 클 라 이언 트 가 반 직렬 화 할 때 만 암 호 를 읽 을 수 있 습 니 다.이렇게 하면 어느 정도 직렬 화 대상 의 데이터 안전 을 보장 할 수 있다.
해결:직렬 화 과정 에서 가상 기 회 는 대상 클래스 의 writeObject 와 readObject 방법 을 호출 하여 사용자 정의 직렬 화 와 반 직렬 화 를 시도 합 니 다.이러한 방법 이 없 으 면 기본 호출 은 Object OutputStream 의 default Write Object 방법 과 Object InputStream 의 default ReadObject 방법 입 니 다.사용자 정의 writeObject 와 readObject 방법 은 사용자 가 직렬 화 과정 을 제어 할 수 있 도록 합 니 다.예 를 들 어 직렬 화 과정 에서 직렬 화 된 수 치 를 동적 으로 바 꿀 수 있 습 니 다.이 원 리 를 바탕 으로 실제 응용 에서 사용 할 수 있 고 민감 한 필드 의 암호 화 작업 에 사용 할 수 있 으 며 리스트 3 은 이 과정 을 보 여 주 었 다.
   3.            

private static final long serialVersionUID = 1L;

private String password = "pass";

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

private void writeObject(ObjectOutputStream out) {
try {
PutField putFields = out.putFields();
System.out.println("   :" + password);
password = "encryption";//    
putFields.put("password", password);
System.out.println("      " + password);
out.writeFields();
} catch (IOException e) {
e.printStackTrace();
}
}

private void readObject(ObjectInputStream in) {
try {
GetField readFields = in.readFields();
Object object = readFields.get("password", "");
System.out.println("       :" + object.toString());
password = "pass";//    ,         
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}

}

public static void main(String[] args) {
try {
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("result.obj"));
out.writeObject(new Test());
out.close();

ObjectInputStream oin = new ObjectInputStream(new FileInputStream(
"result.obj"));
Test t = (Test) oin.readObject();
System.out.println("       :" + t.getPassword());
oin.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
    3   writeObject    ,        ,  readObject     password     ,          ,           ,        。

좋은 웹페이지 즐겨찾기