web-dev-qa-db-ja.com

ヒープvsスタックvsパーマスペース

  • Javaメモリスペース(パーマスペース、スペーススタック、ヒープスペース))の違いは何ですか?
  • JVMはいつどちらかを使用しますか?
  • Scala/Groovyなどを使用している場合、違いはありますか?
37
caarlos0

単に

  • ヒープスペース:すべてのライブオブジェクトがここに割り当てられます。
  • スタック空間:メソッド呼び出しまたは変数のインスタンス化での変数のオブジェクトへの参照を格納します。
  • パーマスペース:ロードされたクラス情報を保存します

例えば:

Student std = new Student();

上記の行を実行すると、メモリステータスは次のようになります。

  • ヒープ:「new Student()」のストア
  • スタック:「std」に関する情報を格納します
  • パーマスペース:学生クラスに関する情報を保存します
83
Kowser

このような古い質問に回答を追加してください。現在の回答は素晴らしいですが、静的コードとJava 8の更新のため、いくつかのEdgeケースがありません。

概要

  • スタック
    • スレッドごとに割り当て
    • ローカル参照とプリミティブを格納します
    • これはスコープ付きメモリです-メソッドまたはスレッドが終了すると、スタック内のすべてのデータが失われます
    • アクセスが最も速いため、ローカルプリミティブはローカルオブジェクトよりも高速に使用できます
  • ヒープ
    • 割り当てられたすべてのオブジェクトインスタンスがここに存在します
    • 世代に分割、最年少の世代が最初にGCが見える場所
    • すべてのスレッドで使用できるため、割り当てと割り当て解除を同期する必要があります
    • このメモリは断片化する可能性があります(しかし、通常これを自分で管理することはありません
  • PermGen
    • ロードされたクラス情報を格納します
    • 不変情報を格納します(プリミティブ、インターンされた文字列)
    • 静的クラスを格納 members

コード例

public class SimpleVal { //The Class (loaded by a classloader) is in the PermGen

    private static final int MAGIC_CONSTANT = 42; //Static fields are stored in PermGen
    private static final SimpleVal INSTANCE = new SimpleVal(1); //Static field objects are created in the heap normally, with the reference in the PermGen ('class statics' moved to the heap from Java 7+)
    private static SimpleVal previousInstance; //Mutable static fields also have their reference in PermGen so they can easily cause memory leaks

    private int value; //Member variables will be part of the heap

    public SimpleVal(int realValue) {
        value = realValue;
        ...
    }

    public static int subtract(SimpleVal val1, SimpleVal val2) {
         ....
    }

    public int add(SimpleVal other) { //Only one copy of any method (static or not) exists - in PermGen
         int sum = value + other.value; //Local values in methods are placed in the Stack memory
         return sum;
    }

}

public static void main(String[] args) {

    SimpleVal val1 = null;
    SimpleVal val2 = new SimpleVal(3); //Both of these variables (references) are stored in the Stack 

    val1 = new SimpleVal(14); //The actual objects we create and add to the variables are placed in the Heap (app global memory, initially in the Young Gen space and later moved to old generation, unless they are very large they can immediately go old gen)

    int prim = val1.add(val2); //primitive value is stored directly in the Stack memory
    Integer boxed = new Integer(prim); //but the boxed object will be in the heap (with a reference (variable) in the Stack)

    String message = "The output is: "; //In Java 7+ the string is created in the heap, in 6 and below it is created in the PermGen
    System.out.println(message + prim);

}

Java 8注:PermGenスペースは、いわゆるメタスペースに置き換えられました。これは引き続き同じように機能しますが、自動的にサイズ変更できます。デフォルトでは、メタスペースはネイティブメモリのサイズを最大(JVMパラメータで指定)まで増やしますが、PermGenは常にヒープメモリに隣接する固定の最大サイズを持っています。

Android Note:From Android 4.0(実際には3.0以降)Android説明されているメモリコントラクトを尊重します。ただし、古いバージョンでは 実装が壊れていました 。Android-Davlikの「スタック」メモリは、実際にはレジスタベースです(命令サイズとカウントは2つで異なりますが、開発者向けです)機能は変わりません)。

最後に、詳細については、StackOverflowでこの主題に対して私が今まで見た中で最良の答えは here です。

9
Nick Cardoso