堆与堆叠对比彼尔姆空间

caa*_*os0 37 java memory heap jvm

  • Java内存空间(Perm Space,Space Stack,Heap Space)之间有什么区别?
  • JVM何时使用其中一个?
  • 如果我使用Scala/Groovy /等,是否存在差异?

Kow*_*ser 83

只是

  • 堆空间:所有活动对象都在此处分配.
  • 堆栈空间:在方法调用或变量实例化中存储对变量对象的引用.
  • Perm空间:存储已加载的类信息

例如:

Student std = new Student();
Run Code Online (Sandbox Code Playgroud)

执行上面的行后,内存状态将是这样的.

  • 堆:存储"新学生()"
  • 堆栈:存储有关"std"的信息
  • Perm Space:存储有关Student class的信息

  • Stack还存储原始文字. (12认同)
  • @Angel我不是在谈论java.util.Stack,我在谈论[stack](http://en.wikipedia.org/wiki/Stack_(data_structure)).如果东西没有存储在堆栈中,你怎么能从堆栈中检索它?如果你想谈论汇编程序而不是堆栈概念,i386上的`push`操作码_stores_堆栈中的数据 - 它调整一个寄存器,然后将数据写入它指向的内存中的位置.这种写入内存的行为在一些汇编语言(例如6502)*store*中被调用.我开始认为你对"商店"一词有一些特殊的定义. (2认同)

Nic*_*oso 9

原谅我为这样一个老问题添加答案 - 目前的答案很棒,但由于静态代码和Java 8更新而错过了几个边缘情况.

概观

    • 每个线程分配
    • 存储本地引用和基元
    • 这是作用域内存 - 当方法或线程结束时,堆栈中的所有数据都将丢失
    • 具有最快的访问权限,因此本地原语比本地对象使用起来更快
    • 此处存在所有已分配的对象实例
    • 分为Generations,最年轻的一代是GC看起来的第一个位置
    • 可用于所有线程,因此应同步分配和解除分配
    • 此内存可能会碎片化(但您通常不会自行管理)
  • PermGen的
    • 存储已加载的类信息
    • 存储不可变信息(Primatives,interned Strings)
    • 存储静态类成员

示例代码

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);

}
Run Code Online (Sandbox Code Playgroud)

Java 8注意: PermGen空间被所谓的Metaspace所取代.这仍然具有相同的功能,但可以自动调整大小 - 默认情况下,Metaspace自动将其在本机内存中的大小增加到最大值(在JVM参数中指定),但PermGen始终具有与堆内存相邻的固定最大大小.

Android注意:从Android 4.0(实际上是3.0)Android应该尊重所描述的内存合同 - 但在旧版本中,实现被破坏了.Android-Davlik中的"堆栈"内存实际上是基于寄存器的(指令大小和计数在两者之间有所不同,但对于开发人员而言,功能保持不变).

最后,有关更多信息,我在StackOverflow上看过这个主题的最佳答案就在这里