以前、Listを使ったバッファのようなものを作らなければならなくなったときに、
使用メモリ量を概算で求めなければならくなり、そのときは以下のような方法でそれを求めました。
import java.lang.instrument.*;
import java.util.*;
class agent {
public static Instrumentation Inst;
public static void premain(String aargs, Instrumentation ins) { Inst = ins; };
}
class getaboutobjectsize extends Object {
public getaboutobjectsize() { super(); };
public long GetAboutObjectSize() { return(agent.Inst.getObjectSize(this)); };
}
class StringGAOS extends getaboutobjectsize {
private String Str;
public StringGAOS(String str) { Str = new String(str); };
public long GetAboutObjectSize() {
return(agent.Inst.getObjectSize(this) +
new Integer(Str.length()).longValue() * 2 + agent.Inst.getObjectSize(Str));
};
}
class IntegerGAOS extends getaboutobjectsize {
private Integer Int;
public IntegerGAOS(Integer num) { Int = new Integer(num); };
public long GetAboutObjectSize() {
return(agent.Inst.getObjectSize(this) + agent.Inst.getObjectSize(Int));
};
}
class StrIntGAOS extends getaboutobjectsize {
public IntegerGAOS Int;
public StringGAOS Str;
public StrIntGAOS(String str, int num) {
Int = new IntegerGAOS(num);
Str = new StringGAOS(str);
};
public long GetAboutObjectSize() {
return(agent.Inst.getObjectSize(this) + Str.GetAboutObjectSize() + Int.GetAboutObjectSize());
};
}
class ListGAOS extends AbstractList {
public static final int MaxLineNumber = 100;
private getaboutobjectsize Line[];
public ListGAOS() {
int Int1;
Line = new getaboutobjectsize[MaxLineNumber];
for (Int1 = 0; Int1 < MaxLineNumber; Int1 ++) Line[Int1] = new getaboutobjectsize();
};
public Object get(int index) {return(Line[index]); };
public int size() { return(MaxLineNumber); };
public void SetLine(int index, getaboutobjectsize item) { Line[index] = item; };
public void RemoveLine(int index) { Line[index] = new getaboutobjectsize(); };
public long GetAboutObjectSize() {
long Long1 = 0l;
int Int1;
for (Int1 = 0; Int1 < MaxLineNumber; Int1 ++)
Long1 += Line[Int1].GetAboutObjectSize() + agent.Inst.getObjectSize(Line[Int1]);
return(Long1 + agent.Inst.getObjectSize(this));
};
}
public class sizeoflist {
public static void main(String args[]) {
ListGAOS BufferList = new ListGAOS();
BufferList.SetLine(0, new StringGAOS("0123456789"));
BufferList.SetLine(1, new IntegerGAOS(100));
BufferList.SetLine(2, new StrIntGAOS("abcdefghijklmnopqrstuvwxyz", -1));
System.out.println(Long.toString(BufferList.GetAboutObjectSize()));
BufferList.SetLine(3, new StringGAOS("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
System.out.println(Long.toString(BufferList.GetAboutObjectSize()));
BufferList.RemoveLine(0);
System.out.println(Long.toString(BufferList.GetAboutObjectSize()));
};
}
オブジェクトの大きさやメモリ上でのアドレスを取得することは、
プログラミング言語においての基本的な機能のはずです。
よってこれらの機能は、全てのオブジェクトの基底クラスのObjectクラスに実装されているべきものだと思います。
しかし、これが実装されていない(実行時クラスは取得できるのに)ということは、
Javaの言語仕様的にこれらの行為を『積極的』に『拒絶』していると考えられます。
もしこのような機能を使いたいのであれば、
使う方の『責任』で全て『手動』で実装しなければならないということです。
補足
>ここで data.length は 12 になります。 >これでこのデータのサイズは12バイトと判り、これを読み取ればUndo/Redoもできるわけです。 具体的に、Undoバッファを実装された経験をお持ちでしょうか? テキストエディタの例で言うなら、文字列データそのものはどこにあるのでしょうか? イメージエディタなら、そのラスタデータはどこにあるのでしょうか?これを含んでUndoバッファです。 >「参照先オブジェクトのサイズを含む、オブジェクトのサイズ」を計測する方法がなくても、 >配列のlengthフィールドを参照するだけでサイズが測れると思うのです。 例えば、エディタのテクストがフォント名を持っているかもしれない(またはnullかも知れない), フォント色を持っているかもしれない(〃),バックグラウンドのテクスチャパターンを持ているかも知れない(〃) 等を考えてみてください。 UndoManagerがUndoableEditのオブジェクト構造を予め全てを知っていなくてはいけないよう実装なら、 オブジェクト指向言語での設計の利点は殆どなくなるでしょう。