- PR -

オブジェクトのシリアライズ時のバイトサイズの疑問

1
投稿者投稿内容
Java初心者
会議室デビュー日: 2006/08/15
投稿数: 4
投稿日時: 2006-08-15 15:51
初めて投稿させていただいています。
「Java初心者」と申します。

オブジェクトのシリアライズを行った場合、バイトサイズの疑問があります。
例えば、下記のようなコードを実行した場合、

---
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.SerializationUtils;

public class Test {

public static void main(String[] args) throws Exception {

List list = new ArrayList();
String data = "DATA";

for (int ii = 0; ii < 100; ii++) {
list.add(data);
}

System.out.println("LIST SIZE:" + SerializationUtils.serialize((Serializable)list).length);
System.out.println("DATA SIZE:" + SerializationUtils.serialize(data).length);
}

}

環境
JDK1.4.2
Jakarta Commons Lang 2.1
---

結果は、

LIST SIZE:560
DATA SIZE:11

と、なります。
ここで疑問なのが、
「なぜ、[DATA SIZE]が 11 にもかかわらず、[LIST SIZE]が 560 なのか?」
と、いうことです。

単純に考えると、ループで [変数:data] を 100 回 add しているわけですから、
[LIST SIZE]は、[DATA SIZE]×100 で 1100 以上になりそうなのですが...

ご存知の方、是非とも私にご伝授お願いいたします。
holic
ベテラン
会議室デビュー日: 2004/08/24
投稿数: 74
投稿日時: 2006-08-15 16:09
ちょっと勘違いしていたので、修正。

List は、date へのリファレンスを保持しているだけで、date そのものを保持しているわけではありません。

[ メッセージ編集済み 編集者: holic 編集日時 2006-08-15 16:15 ]
Java初心者
会議室デビュー日: 2006/08/15
投稿数: 4
投稿日時: 2006-08-15 16:22
早速のご返信ありがとうございます。

「List は、date へのリファレンスを保持しているだけ」
と、ありますが、もう少し詳しくご伝授願いませんでしょうか?

お手数をおかけしますが、お願いいたします。
holic
ベテラン
会議室デビュー日: 2004/08/24
投稿数: 74
投稿日時: 2006-08-15 19:42
すみません。
ちゃんと調べたら大嘘でした。
JDK1.5 で確認しましたが、1.4 でも同じ動作のようです。

ArrayList は、自身をシリアライズする際、リストに含まれるオブジェクトを、
java.io.ObjectOutputStream#writeObject を使ってシリアライズしようとします。

この writeObject に仕掛けがあって、同一のオブジェクトをシリアライズしようとしたときは、個別にシリアライズするのではなく、以前にシリアライズしたオブジェクトへの参照を書き出すという動作をします。また、同一のクラスをシリアライズする場合は、クラスの情報を省いて、インスタンスの情報のみをシリアライズします。

というわけで、最初のコードだと、リストの最初の String がシリアライズされ、2番目以降の String は参照としてシリアライズされるという挙動となるため、最初のような結果になるようです。

#詳しくは、ObjectOutputStream のソースをどうぞ

勉強になりました。ありがとうございました。
Java初心者
会議室デビュー日: 2006/08/15
投稿数: 4
投稿日時: 2006-08-16 09:27
holic 様

わざわざ調べていただき、誠にありがとうございます。

ObjectOutputStream のソースをみてみました。
なんとなく理解することができました。
ありがとうございます。

ソースを読むだけでなく、どこかに holic 様がおっしゃる様な文章が
あればよいのですか...

それとも、「シリアライズはこうだ!」と思うしかないのでしょうか?
未記入
常連さん
会議室デビュー日: 2005/05/07
投稿数: 32
投稿日時: 2006-08-16 10:49
ここの資料でどうでしょうか?
http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/serialization/index.html
Java初心者
会議室デビュー日: 2006/08/15
投稿数: 4
投稿日時: 2006-08-16 11:47
未記入様

ご返信ありがとうございます。

教えていただいたURLの
http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/serialization/spec/serial-arch.html#4176
にある

---
「1.2 オブジェクトストリームへの書き込み」
writeObject メソッド (「2.3 writeObject メソッド」を参照) は、指定されたオブジェクトを直列化し、オブジェクトグラフにある他のオブジェクトへのそれの参照を再帰的に処理 (トラバース) して、そのグラフを完全に直列化した表現を作成します。ストリーム内でオブジェクトに対する初めての参照があると、そのオブジェクトが直列化または外部化され、そのオブジェクトのハンドルが割り当てられます。そのオブジェクトに対するそれ以後の参照は、そのハンドルとしてエンコーディングされます。オブジェクトハンドルを使用すれば、オブジェクトにおいて当然起こる共用参照や循環参照が保存されます。オブジェクトのそれ以後の参照ではそのハンドルだけを使用するため、非常に簡潔な表現が可能になります。
---

の所でしょうか?
確かに writeObject のソースはこのようになっていたような気がします。
1

スキルアップ/キャリアアップ(JOB@IT)