4

Java でのメモリ割り当てが実行時とコンパイル時のどちらで行われるかについて混乱しています。

例えば:

class Test{
  int a;
  public Test(){
    a=10;
  }
};

// somewhere else
Test t = new Test();

a実行時またはコンパイル時に割り当てられますか? コンパイル時に、コンパイルされた .class ファイルを直接取得する VM 上で Java が実行されるのはどうしてですか?

また:

  • いつa値が割り当てられます10か?

  • 参照変数に対してどのように機能しますtか?

ありがとう。

4

4 に答える 4

9

コンパイル時にメモリ割り当ては発生しません。ロード時と実行時のみ。

コンパイル時に .class ファイルが生成されます。

プログラムを実行するには、メイン クラスが必要であることを忘れないでください。.class ファイルへのクラスパスを指定して Java を使用してプログラムを実行すると、ロードやリンクなどの手順が必要になります。

クラスローダーはファイルを permgen にロードします。

メインメソッドが呼び出されると、スタックが作成され、ローカル変数がそこに配置されます

ランタイムがnewに遭遇すると、ヒープ上にオブジェクトを作成し、テストに必要なメモリのように必要なメモリをそこに割り当てます。

于 2012-09-05T16:00:37.787 に答える
5

ローカル変数とプリミティブや参照などのメソッドパラメーターは、コンパイル時にスタック上の場所に概念的に割り当てられます。

実行時に、これがメモリ内でどのように配置されているかを反映することは保証されていません。

ヒープ上のオブジェクトの割り当ては、実行時にのみ発生します。

コンパイル.classファイルを直接取得するVMでJavaを実行する場合、どのように可能ですか。

コードがどのようにコンパイルされるかを知っているのはVMだけなので、コンパイル時にメモリ割り当てを行うことはできません。

割り当てられた値はいつですか10

割り当てが発生する行。使用されていない場合、JITはそれを破棄できるため、まったく発生しない可能性があります。

また、同じ質問が参照変数tを表します。

t=オブジェクトが構築された後の場所に割り当てられます。

于 2012-09-05T16:03:06.337 に答える
1

Javaでは、実行時に作成されるオブジェクトが作成されない限り、クラスはロードされません。そのため、クラスがロードされると、クラスの「a」などのメンバー変数はスペースを取得し、オブジェクトにも同じように実行時にスペースが割り当てられます。

于 2012-12-24T11:51:11.880 に答える
1

ええと、これはちょっとばかげています。このスレッド全体からあなたが望む正確な答えが得られるかどうかはわかりません。実際にあなたが求めているのは、コンパイラの内部構造であり、ほとんどの人は気にしません。

ほとんどの場合、Java コンパイラは自動メモリ管理を使用するため、何を実行するかしないかを決定するのはコンパイラ次第であり、これはバージョン間で変わる可能性があります。

しかし、これを説明する前に、私の表記法を明確にしたいと思います:

  1. プリミティブでない Java オブジェクトを参照する場合は、[オブジェクト] を使用します。
  2. 値と識別子を持つメモリ内の場所を参照するときに [オブジェクト] を使用します。
  3. [プリミティブ] は、Java のプリミティブ型 (int、double、float など、string を除く) のいずれかで構成される [オブジェクト] を参照するために使用します。
  4. 文字列は Java の特殊なケースであり、オブジェクトですが、他のオブジェクトとは異なる方法で処理される場合があります。

    [オブジェクト] には特別なプロパティがあります。これには値と識別子があり、識別子が値に解決されるプロセスと、それが発生する時点はバインディングのタイプによって異なります。

    コンパイル時にバインディングを解決でき、その値またはメソッドがコンパイル時に既知である静的バインディングがあります。これは「早期」バインディングとも呼ばれます。例えば。

    int a = 0; // AND //print() などの直接関数呼び出し;

    動的バインディングもあり、識別子と値の間、またはサブプログラムとプログラムとの間のバインディングは、実行時まで発生しません。これは、「遅延」バインディングとも呼ばれます。例えば。

    public void foo(java.util.List リスト) { list.add("バー"); }

    ハイブリッドの種類のバインドもありますが、それについては触れません。なぜなら、Java にそれがあることを発見していないからです。

    現在、バインディングは、変数が特定のスコープ内に「存在する」という考えであるスコープにも非常に密接に関連しています。それは私が実際には入りたくない議論のトピックであり (スコーピングはクマのようなものです)、この投稿を小説ではなく小説にします。

    Java でのメモリ割り当てのしくみは、いくつかの要因によって異なります。

    1. [オブジェクト]、[オブジェクト]、または [プリミティブ] への参照がコンパイル時にわかっていて、静的バインディングが発生する可能性がある場合、コンパイラはそれらのオブジェクトにメモリを割り当てる可能性があります (どのように割り当てなかったかに注意してください。 t は括弧を使用します) をコンパイル時に使用します。

    2. [オブジェクト]、[オブジェクト]、または [プリミティブ] への参照をコンパイル時に認識できず、動的バインディングを使用する必要がある場合、コンパイラは実行時にそれらのオブジェクトにメモリを割り当てる可能性があります。

    Java が実行時に割り当てられたオブジェクトを処理する方法は、どのバインディングがどのタイプに使用されたかによって異なります。

    1. 静的バインディング
      • [Object] の一種であるオブジェクトは、コンパイル時に参照がスタックに配置されますが、メモリは実行時にヒープに割り当てられます。(怠惰)。
      • [プリミティブ] の一種であるオブジェクトは、実行時にバインドおよび割り当てられます。
      • 文字列は特殊なケースですが、通常は [Object] の場合と同様に扱われます
    2. 遅延バインディング
      • スタックとヒープへの割り当ては実行時に行われます。

    要約すると、それについて心配する必要はありません。そうすることはあなたにとって大きな頭痛の種です。

    これについて私が間違っている場合は、誰かが私に知らせてください。私は少し錆びています。

于 2012-09-05T17:58:04.970 に答える