Javaシリアル化メカニズムは、クラスが逆シリアル化するJVMに認識されていることを前提としており、クラス定義を送信しません。特に、オブジェクトをシリアル化する場合、そのクラスのバイトコードは送信せず、受信側のVMに特定の名前のクラスのオブジェクトClass
を検索するように指示するだけです。Class
また、オブジェクトはJVMで定義されたクラスを表すことにも注意してくださいClass
。つまり、クラスのバイトコードはすでにロードされています。クラスをロードした後にそのバイトコードを生成するためにクラスにコンパイルしようとすることはほとんど意味がありません。
したがって、どういうわけかクライアントにクラス定義を取得する必要があります。最も簡単なアプローチは、クライアントが必要とする他のクラスと同じようにこれを行うことです(クライアントのjarファイルにパックするか、クライアントプログラムのインストールに使用する手段を使用します)。それが不可能な場合は、たとえば、を使用してネットワーク経由でクラス定義をロードするURLClassLoader
か、シリアル化ストリームを介してクラスファイルを送信し、クライアントで受信したらClassLoader.defineClass
クラスのロードに使用できます。
PS:この問題は、クラスに名前が付けられているかどうかに完全に依存していません。次のテストコードは、匿名クラスのオブジェクトを正常にシリアル化および逆シリアル化できることを示しています(受信側のVMにクラス定義がある場合)。
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
Serializable payload = new Serializable() {
@Override
public String toString() {
return "hello from the anonymous class";
}
};
oos.writeObject(payload);
oos.writeObject(payload.getClass());
}
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) {
System.out.println(in.readObject());
System.out.println(in.readObject());
}