Java オブジェクトのデシリアライズについて
Javaにおけるデシリアライズは、バイナリ形式や文字列形式で保存されたオブジェクトのデータを読み取り、元のJavaオブジェクトに再構築するプロセスです。以下では、デシリアライズの基本、用途、例、そして注意点について詳しく解説します。
デシリアライズとは
デシリアライズは、シリアライズされたオブジェクトデータを元のオブジェクトに再構築するプロセスを指します。この機能は、オブジェクトをファイルやネットワーク経由で転送する際や、長期間保存する場合に便利です。
シリアライズとデシリアライズはセットで使用されることが多く、シリアライズによって保存されたデータは、デシリアライズによって元のJavaオブジェクトに復元されます。
デシリアライズの実装方法
Javaでデシリアライズを実現するには、以下の手順を踏む必要があります。
- デシリアライズしたいクラスが
Serializable
インターフェースを実装していることを確認します。 - シリアライズされたデータを読み取るために
ObjectInputStream
を使用します。 - シリアライズされたデータが保存されたファイルまたは入力ストリームを開きます。
ObjectInputStream
のreadObject()
メソッドを呼び出して、オブジェクトを復元します。
デシリアライズの例
基本的な例
import java.io.*;
// シリアライズ可能なクラス
class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
public class DeserializationExample {
public static void main(String[] args) {
// ファイル名
String filename = "person.ser";
// デシリアライズ
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) {
Person person = (Person) ois.readObject();
System.out.println("Deserialized Person: " + person);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
この例では、Person
オブジェクトがシリアライズされてファイルに保存され、後でデシリアライズされて復元されます。
カスタム読み取りメソッド
import java.io.*;
class CustomPerson implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private transient int age; // シリアライズされない
public CustomPerson(String name, int age) {
this.name = name;
this.age = age;
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
this.age = 30; // シリアライズ後にデフォルト値を設定
}
@Override
public String toString() {
return "CustomPerson{name='" + name + "', age=" + age + "}";
}
}
public class CustomDeserializationExample {
public static void main(String[] args) {
String filename = "customPerson.ser";
// デシリアライズ
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) {
CustomPerson person = (CustomPerson) ois.readObject();
System.out.println("Deserialized CustomPerson: " + person);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
この例では、カスタム読み取りメソッドを使って、transient
フィールドに値を設定しています。
セキュリティ上の注意点
デシリアライズにはいくつかのセキュリティリスクが伴います。特に、信頼できないソースからのシリアライズデータを処理する場合、デシリアライズの過程で任意のコードが実行される可能性があります。
- 対策1: 信頼できるデータソースのみを処理する。
- 対策2:
ObjectInputStream
を拡張し、クラスのホワイトリストを実装する。 - 対策3: デシリアライズ処理を行う前に入力データを検証する。
一般的なエラーと対処法
InvalidClassException
クラスの serialVersionUID
が変更された場合に発生します。デシリアライズ時に同じ serialVersionUID
を持つ必要があります。
ClassNotFoundException
デシリアライズ時に必要なクラスがクラスパス上に存在しない場合に発生します。必要なクラスが利用可能であることを確認してください。
NotSerializableException
シリアライズ可能なクラスでない場合に発生します。対象のクラスが Serializable
インターフェースを実装しているか確認してください。
これらの問題を回避するために、適切なエラーハンドリングを実装することが重要です。