- PR -

ちょっと突っ込んだ質問ですが

投稿者投稿内容
isseki
大ベテラン
会議室デビュー日: 2001/11/05
投稿数: 107
投稿日時: 2002-12-16 16:11
classロードする時のJVMの動き(static変数の初期化以外)と
class がnewされる時のJVMの動きが何が違うのでしょうか。

ご存知の方、ご教授お願いいたします。
jack_pma
常連さん
会議室デビュー日: 2002/11/15
投稿数: 35
お住まい・勤務地: 埼玉
投稿日時: 2002-12-16 17:09
ロードって、Class.forNameとかのことですよね?

一番大きな違いは、ロードしただけではインスタンスは生成されません、ということです(もっと細かい違いまでは私じゃ解らないですが)。

newはそのクラスのインスタンスを生成します、そして、その時点でまだロードされていないクラスの場合はJVMによって自動的にロードされます。また、一度ロードしたクラスはその後再びforNameとかしても以前にロードしたクラスが使われるので、普通は各クラスにつき一度しかロードは行われません。

説明が間違ってるとか、もっと詳しくご存知の方がいたらご教授願います。
jack_pma
常連さん
会議室デビュー日: 2002/11/15
投稿数: 35
お住まい・勤務地: 埼玉
投稿日時: 2002-12-16 17:19
自己レスです。
Class.forNameはロードのためのメソッドじゃなかったですね、これはClassオブジェクトを返すために、まだロードされていなければロードしているだけですね。
ロードさせるためのメソッドはClassLoader.loadClassですかね、こっちでもロード済みのクラスを再ロードしないことは同じみたいですが(このへんはClassLoaderのAPI仕様に載ってます)。
isseki
大ベテラン
会議室デビュー日: 2001/11/05
投稿数: 107
投稿日時: 2002-12-16 19:21
jack_pmaさん
こんにちは
ご返答ありがとうございます。
おっしゃることは全部正しいと思います。

>もっと細かい違いまでは私じゃ解らないですが
私はちょうど少し細かい事を知りたいのです。

ロードって
コードをファイルからメモリへ展開し、
この時点でstaticなメソッドを実行できるようになります。

instance化は何をやるのでしょうか。
すでにロードしているコードをさらに別のメモリへコピーするのでしょうか。

ご存知の方宜しくお願いいたします。







未記入
ぬし
会議室デビュー日: 2002/03/28
投稿数: 255
投稿日時: 2002-12-16 20:33
>classロードする時のJVMの動き(static変数の初期化以外)と
>class がnewされる時のJVMの動きが何が違うのでしょうか。
newの対象はインスタンスでクラスではないのでは?
#Java言語でもJavaバイトコードのいずれでもそのはず.

ちなみに,newにしろstaticフィールドアクセスにしろ,必要な
時点でクラスは自動的にロードされます.ロードするのは必ず
しも初回実行時とは限りません.なんならJVMが起動した時点や,
或いはOSの起動時にあらゆるクラスをロードしても,JVM仕様上の
問題は無いはずです.
TO-R
ベテラン
会議室デビュー日: 2002/07/11
投稿数: 93
投稿日時: 2002-12-16 20:58
>issekiさん

引用:

ロードって
コードをファイルからメモリへ展開し、
この時点でstaticなメソッドを実行できるようになります。

instance化は何をやるのでしょうか。
すでにロードしているコードをさらに別のメモリへコピーするのでしょうか。

ご存知の方宜しくお願いいたします。


以下、個人的な解釈なので、正解ではないかもしれませんが、挙動を見る限り、
大外れはしていないと思います。

ロードすると、(コードを含めた)static なものがメモリ上に展開され、
staticな要素へのアクセスが可能になります。
インスタンス化(new)すると、領域を必要とするものがメモリ上に確保
され、それらへのアクセスが可能になります。
インスタンス化は、newするたびに領域を確保するので、staticでない領域は
個々のインスタンスで独立して取られ、staticな領域は最初にとられた
一つだけなので、すべてのインスタンスで共有されます。

  C言語風(さらに外れますが…(^^;)には、
    ロード=struct new_struct { ... }
    インスタンス化=malloc(new_struct)
  みたいな位置づけの解釈をしています。

    構造体に関数へのポインタのエントリがあって、
    malloc()した後、然るべき関数のアドレスを入れたら
    クラス相当のうような気がするのですが…。

何かの足しになるようでしたら、幸いです。
H2
ぬし
会議室デビュー日: 2001/09/06
投稿数: 586
お住まい・勤務地: 港
投稿日時: 2002-12-16 21:21
挙動は実装によって変わってしまいます。一応SunのJVMを例にすると。

クラスをロードした場合
1.バイトコードのクラスをClassオブジェクトとしてメモリにロードする(Loading)
2.クラスの依存関係を調べて必要なスーパークラス・インターフェイスなどをリストアップしてメモリにロードする。(Linking)
3.ロードしたクラスのStatic Initialiserを実行し、Static変数を初期化。必ず先にスーパークラスから初期化するが、インターフェイスはしなくても良い。Static Initialiserの実行とStatic変数の順番はソースコードによる。 (Initialising)

オブジェクトをインスタンス化した場合。
1.クラスとスーパークラスで宣言されているインスタンス変数用のメモリを確保
2.コンストラクタの実行(コンストラクタ内で明示されていれば別のコンストラクタを先に実行)

となります。オブジェクトのインスタンス化はそのつどインスタンス変数用のメモリを確保する必要がありますが結構シンプルです。クラスのローディングは大抵一回しか行われませんが依存性などを処理しないといけないのでかなり複雑です。これはオブジェクトの生成にかかるコストをできるだけ下げるためです。

クラスのロードはClassLoaderを実装することによって違う処理をするようにしたりできますが、オブジェクトのインスタンス化は各クラスのコンストラクタが使われます。

クラスのロード時には最低でもstatic変数、staticメソッドとインスタンスメソッドがメモリにロードされる必要がありますが、オブジェクトの生成にはインスタンス変数のみのメモリが必要です。参照やパディングがあるのでもうちょっと必要ですが・・・。

参考: 「The JavaTM Virtual Machine Specification」(英語)
http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html

[ メッセージ編集済み 編集者: H2 編集日時 2002-12-16 21:35 ]

[ メッセージ編集済み 編集者: H2 編集日時 2002-12-16 22:22 ]
isseki
大ベテラン
会議室デビュー日: 2001/11/05
投稿数: 107
投稿日時: 2002-12-17 13:07
みなさん
ご返答ありがとうがざいます。
ほんとうに勉強になりました。

皆さんの見解をまとめますと、以下のようでしょうね。
A.loadする時は、*.classのコード部分とstaticの部分(static method とstatic variable)をメモリへ展開(確保)する

B.instance化する時は
1.クラスとスーパークラスで宣言されているインスタンス変数用のメモリを確保
2.コンストラクタの実行(コンストラクタ内で明示されていれば別のコンストラクタを先に実行)


ただ、コードの複製に関してはどなたも
触れませんでしたので、改めて質問させていただきたいです。

JAVAコード(JAVAの文、例えばfor(..))はnewする時に必ずどっかのメモリへ複製するの
でしょうか。

よろしくお願いいたします。











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