🧊

入門シリアライズ

に公開

環境

  • JDK 21

シリアライズって何?

一言で言うと「インスタンスをファイル化する技術」です。インスタンスをファイル化することを シリアライズ 、ファイルからインスタンスに戻すことを デシリアライズ と言います。

シリアライズを利用することで、次のようなことが可能になります。

  • インスタンスを一時保存して、後でまた使う
  • ファイルを転送して、他の場所でインスタンスを使う

シリアライズは、われわれ開発者が使うことはほぼありません。次で説明するように、アプリケーションんサーバーなどがわれわれの見えないところで行なっていることがほとんどです。しかし、見えないところで何が起こっているかを知ることは重要です。なので1回は自分でもシリアライズのコードを書いてみることをお勧めします。

シリアライズとHttpSession

特に業務でよく出てくるのはHttpSessionに保存する値です。Tomcatなどのアプリケーションサーバーは、HttpSessionsetAttribute()で保存された値をシリアライズすることがあります。

HttpSessionとは何ぞや、については下記の資料をご確認ください。
Webアプリケーションセキュリティの基礎とSpring Bootでの実装

これによって、次のようなことが可能になります。

  • アプリケーションサーバーが一時停止時に、HttpSessionに保存されていた値をシリアライズしてファイルとして保存する。すると再起動時にデシリアライズすることで、HttpSessionに保存されていた値を再び利用可能になる

  • アプリケーションサーバーがクラスター構成(複数台構成)になっている際、HttpSessionに保存されていた値をシリアライズして、そのファイルをクラスター内の別サーバーに転送する。これによりクラスター内の全サーバーで同じ値がHttpSessionに保存される

Serializableインタフェース

すべてのインスタンスがシリアライズ可能なわけではありません。 java.io.Serializableインタフェース を実装したクラスのインスタンスのみ、シリアライズ可能です。

今回はこのインタフェースを実装して、次のようなクラスを作成します。

Person.java
package com.example;

import java.io.Serializable;

public record Person(String name, int age) implements Serializable {
}

もし、このインタフェースを実装していないクラスのインスタンスをシリアライズしようとすると、java.io.NotSerializableExceptionがスローされます。

Exception in thread "main" java.io.NotSerializableException: com.example.Person
	at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1200)
	at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:358)
	at com.example.SerializationMain.main(SerializationMain.java:13)

シリアライズしてみる

シリアライズは ObjectOutputStream#writeObject()メソッド で行います。

SerializationMain.java
package com.example;

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

public class SerializationMain {
  public static void main(String[] args) throws Exception {
    Person person = new Person("Alice", 30);
    try (
        FileOutputStream fos = new FileOutputStream("person.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos)
    ) {
      oos.writeObject(person);
      System.out.println("シリアライズが正常に完了しました。");
    }
  }
}

これを実行すると、カレントフォルダにperson.serというファイルが作成されます(ファイル名やファイルの拡張子には特に制限はありません)。これがシリアライズされたPersonインスタンスです。

デシリアライズしてみる

デシリアライズは ObjectInputStream#readObject()メソッド で行います。

DeserializationMain.java
package com.example;

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class DeserializationMain {
  public static void main(String[] args) throws Exception {
    try (
        FileInputStream fis = new FileInputStream("person.ser");
        ObjectInputStream ois = new ObjectInputStream(fis)
    ) {
      Person person = (Person) ois.readObject();
      System.out.println("デシリアライズされたPersonインスタンス: " + person);
    }
  }
}
実行結果
デシリアライズされたPersonインスタンス: Person[name=Alice, age=30]

参考資料

Discussion