- PR -

メモリ消費量

1
投稿者投稿内容
ボア
ベテラン
会議室デビュー日: 2002/05/22
投稿数: 78
投稿日時: 2003-06-07 13:33
オブジェクト生成に伴うメモリ消費量についてなのですが、
大雑把に言えば、
1オブジェクトのメモリ消費量 ~= インスタンス変数の数(サイズ)
と考えてよいのでしょうか?
極端な話、どんなに複雑怪奇なロジックを含むメソッドが大量に
定義されていたとしても、インスタンス変数が int 型で1つだけならば、
生成時のメモリ消費は少量で済むのですか?
メソッド自体のプログラム領域としては各オブジェクトで共有されると
思っているのですが。。。
もちろん、スレッドから各メソッドがコールされれば、この中で
使用しているローカル変数分のメモリが消費されるのでしょうけれど、
これはメソッド実行が終了されれば順次破棄されると言う認識で
合ってますでしょうか?
小僧
ぬし
会議室デビュー日: 2002/08/14
投稿数: 526
投稿日時: 2003-06-08 08:10
一般的な認識では、普通に定義されたメソッドは書くインスタンスでは共有されませんよ。メソッドがstaticで定義されていなれば共有されますが。
さて、ここまでは一般的なJavaのお話なんですが、JVMによっては、内部的にどういう実装を行っているかわからないので、もしかしたらコードの共有を行っているJVMがあるかもしれません。特に組み込み用の小型のJVMとかだとあるかもしれない。Javaプログラムが仕様通り動いてくれさえすれば、JVM内で何をしていようと問題ないはずなので。ローカル変数を破棄するタイミングですが、メソッド終了後に破棄されるようです。Javaの場合はスタックがとても大きいようで、普通に使っている分にはオーバーフローがなかなか起こらないみたいです。スレッド内でローカル変数を使うと、256KB〜2MBに制限がかかるらしいです。



未記入
ぬし
会議室デビュー日: 2002/03/28
投稿数: 255
投稿日時: 2003-06-09 10:37
>オブジェクト生成に伴うメモリ消費量についてなのですが、
>大雑把に言えば、
>1オブジェクトのメモリ消費量 ~= インスタンス変数の数(サイズ)
#正確には「1インスタンスのメモリ消費量」ですよね?

>と考えてよいのでしょうか?
詳細は実装依存ですが,多くの実装では「インスタンス変数のサイズ+
ヘッダ部(マークビット,ハッシュ値,クラスID,ハッシュテーブルへの
ポインタ等.詳細は実装依存)」程度になると思います.

>メソッド自体のプログラム領域としては各オブジェクトで共有されると
>思っているのですが。。。
これも実装依存なので,詳細は各JavaVM実装によります.各インスタンスごとに
別々になるように実装しても仕様に準拠した正しいJavaVMと言えるでしょう.
ただ,実際にはそういう無駄をやってるとは,まず考えられませんがね.

次のページなどは参考になるでしょう.
http://www-6.ibm.com/jp/developerworks/java/jalape-vm-index-j.html
ボア
ベテラン
会議室デビュー日: 2002/05/22
投稿数: 78
投稿日時: 2003-06-10 09:20
私の認識で大きく外れてはいないみたいですね。
回答ありがとうございました。参考にします。
Cluster
ぬし
会議室デビュー日: 2003/03/06
投稿数: 289
お住まい・勤務地: 大阪
投稿日時: 2004-02-17 10:13
過去ログを検索してたら、少々古いですがこのスレッドが見つかりました。(^^;
少し便乗して質問させてください。

私が疑問に感じてることもボアさんとほぼ同じで、
「インスタンス変数の定義が全く同じ場合、メソッドのコードの大きさや数によって
インスタンス化によるメモリ消費量がどれくらい異なるのか?」
ということです。この回答としては
 ・Javaの仕様上は決まっていない
 ・従って、JVMの実装に依存する。
 ・ただし、大抵のJVMは、この程度のメモリの節約は行っているだろう(推測)
ということであってるでしょうか?

また、「実装依存」と言う意味では、実装を指定した場合(例えば、Sun Microsystemsが
出してるWindows版JDK付属のJVM(Java.exeになるのかな?)の場合)に、
実際にどうなっているか、どなたかご存じないでしょうか?

# 質問部分を修正

[ メッセージ編集済み 編集者: Cluster 編集日時 2004-02-17 10:27 ]
シュン
ぬし
会議室デビュー日: 2004/01/06
投稿数: 328
お住まい・勤務地: 東京都
投稿日時: 2004-02-17 13:32
実際どうなっているかについては、JVMPIがヒープ消費量を返すAPIを持っていますので、適当なサンプルクラスを作成して、プロファイラでヒープ消費量を計測してみてはいかがでしょうか。

おそらくJ2SEのJVMでは、1インスタンスあたりのヒープ消費量は
・プリミティブフィールド= 型に応じて1〜8byte
(VMの実装によって、型ごとのサイズが異なることはあり得ると思います。)
・オブジェクト参照=4byte
・インスタンスの識別用情報=数byte〜数十byte
・配列オブジェクトの場合は、要素ごとの必要サイズ(byte[]なら1byte)×配列長+識別用情報
といったあたりで収まるのではないかと思います。

メソッドについては、同一クラスで共有されています。インスタンスメソッドコールは暗黙のうちにthisポインタを渡すようにコンパイル時に処理されます。それ以外はstaticメソッドコールと似たような扱いです。たくさんのメソッドがあるクラスオブジェクトをnewしても、メソッドが存在するためにメモリ消費量が多くなる、ということはありません。
悪夢を統べるものさんのおっしゃるように、インスタンスごとにメソッドのコピーをヒープに貼り付けてもJVM仕様的には問題ないのかもしれませんが、実際そのような無駄なことがされているJVMの実装は、おそらくないと思います。

スレッドごとに固有のスタック領域など、ヒープ外に確保されるメモリもありますので、メモリ消費量のプランニングの際はそちらも多少留意された方が良いかと思います。
Cluster
ぬし
会議室デビュー日: 2003/03/06
投稿数: 289
お住まい・勤務地: 大阪
投稿日時: 2004-02-17 14:09
引用:

シュンさんの書き込み (2004-02-17 13:32) より:

メソッドについては、同一クラスで共有されています。インスタンスメソッドコールは暗黙のうちにthisポインタを渡すようにコンパイル時に処理されます。それ以外はstaticメソッドコールと似たような扱いです。たくさんのメソッドがあるクラスオブジェクトをnewしても、メソッドが存在するためにメモリ消費量が多くなる、ということはありません。




回答ありがとうございます。
まさに、この点が知りたかったのです。
非常に参考になりました。

# Webアプリの設計で、session変数にインスタンスを格納する際、メソッドが
# 大きいクラスのインスタンスを多数格納したりしても大丈夫なのかな?と
# 心配だったので。

↑「メソッドが大きい」という日本語はなんか変ですね、我ながら
Emacs信者
常連さん
会議室デビュー日: 2003/08/10
投稿数: 38
投稿日時: 2004-02-17 15:07
実際、オブジェクトのバイトサイズがクラスファイルに比例していたら、とても
java.lang.StringをRMIなどで使うことはできなかったと思います。
1

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