2011-07-23 55 views
30
  • Java内存空间(Perm Space,Space Stack,堆空间)有什么区别?
  • JVM何时使用这个或另一个?
  • 如果我使用Scala/Groovy /等,有区别吗?
+3

相关:http://stackoverflow.com/questions/4848669/perm-space-vs-heap-space ,http://stackoverflow.com/questions/1279449/what-is-perm-space – Mat

+1

[该堆栈是一个实现细节](http://blogs.msdn.com/b/ericlippert/archive/2009/04/ 27 /在堆叠-是-AN-实施-detail.aspx)。对于Java来说可能并不重要,因为它缺少用户定义的值类型,但对于使用垃圾回收语言工作的每个人来说,仍然是重要的读取。 – delnan

+0

其他JVM语言使用相同的标准? – caarlos0

回答

71

只需

  • 堆空间:所有活动对象都在这里进行分配。
  • 堆栈空间:在方法调用或变量实例化中存储对变量对象的引用。
  • 彼尔姆空间:存储加载的类信息

例如:

Student std = new Student(); 

执行上述存储器状态的行之后会是这样。

  • 堆:卖场 “新学生()”
  • 堆栈:关于 “性病”
  • 彼尔姆空间用于存储信息:存储有关Student类
+12

堆栈也存储原始文字。 –

+0

@Daniel:谢谢你的信息。我不知道,我会更多地研究它。 – Kowser

+0

@Daniel:Stack也存储原始文字。你那是什么意思?严格地说,Stack不存储_anything_堆栈中只有方法调用的参数和用于评估表达式的“值”。 –

2

原谅我加入一个答案这样一个古老的问题 - 当前的答案很好,但由于静态代码和Java 8更新,遗漏了一些边缘案例。

概述

  • 栈每线程
    • 分配
    • 存储本地引用和原语
    • 这是区域性存储器 - 当一个方法或线头,所有的数据堆栈丢失
    • 访问速度最快,所以本地原语比你更快本身不是本地对象
    • 所有分配的对象实例存在这里
    • 分为三代,与年轻一代成为首位GC看起来
    • 提供给所有线程,以便分配并且应该同步取消分配
    • 该内存可能会变成碎片(,但您通常不会自己管理它)
  • PermGen的
    • 商店加载的类信息
    • 存储不可改变的信息(Primatives,实习字符串)
    • 商店静态类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的空间与所谓元空间所取代。这个功能仍然相同,但可以自动调整大小 - 默认情况下,Metaspace auto会将其本地内存大小增大到最大值(在JVM params中指定),但PermGen始终具有与堆内存连续的固定最大大小。

Android Note:从Android 4.0开始(从实践3.0开始)Android应该遵守所述的内存合同 - 但在旧版本中为implementation was broken。 Android-Davlik中的'Stack'内存实际上是基于寄存器的(指令大小和计数在两者之间有所不同,但对于开发者来说,功能保持不变)。

最后,以获得更多信息我曾经观察到在StackOverflow上这个问题的最佳答案是here