Java 堆栈内存分配

不少人在Java的书籍中看到过不少关于堆和栈内存的教程以及参考说明, 可是很难解释什么是程序的堆内存以及栈内存java

一: Java 堆内存空间jvm

Java程序运行时使用java Heap 内存为对象以及JRE类分配内存, 不论咱们在什么时候建立何种类型的对象, 他老是在堆内存中建立的函数

Java 垃圾收集器运行在堆内容空间, 释放那些没有任何引用的对象所使用的内存。 在堆内存空间建立的任何对象都具备全局访问权限, 而且能够从程序的任何位置引用this

二: Java 栈内存空间spa

Java 栈内存空间用于执行线程, 栈内存始终遵循LIFO(Last-in-first-out) 顺序, 每当一个方法被执行, 会在栈内存中建立一个新的block 用于保存在函数中定义的基本数据类型变量以及对象的引用变量线程

当方法结束时, this block 改变它的状态为未使用而且可用于执行下一个方法code

堆内存大小与堆内存相比很是少。cdn

三: Java程序中的堆和堆栈内存对象

经过一个简单的程序来理解堆 栈内存的使用状况blog

/** * Created by huanjulu on 12/10/17. */

public class HeapStackTestMemory {

    public static void main(String[] args) { //Line 1

        int i = 1; //Line 2

        Object obj = new Object(); //Line 3

        HeapStackTestMemory mem = new HeapStackTestMemory(); //Line 4

        mem.foo(obj);  //Line 5

    }  //Line 9

    private void foo(Object param) {  //Line 6

        String str = param.toString();  //Line 7

        System.out.println(str);

    } //Line 8

}复制代码

参考上面的java 程序, 下图显示了stack Heap 内存空间的使用状况

咱们来看看执行程序的步骤。

  • 一旦咱们开始运行程序, 它会把全部的运行时类加载到堆内存空间, 在 Line 1 行找到main() 方法, Java Runtime 建立由main() 方法线程使用的栈内存空间
  • 在第二行 咱们建立了原始数据类型的局部变量, 因此它将被存储在main() 方法的栈内存空间
  • 在第3行咱们建立了一个Object 类型的对象, 因此它被建立在Heap 堆内存空间中 而且 Stack 栈内存空间包含对它的引用, 当咱们在第4行中建立Memory 对象时, 会发生相似的过程
  • 如今咱们在第5行调用foo() 方法, 此时会在stack 栈建立一个block 供foo() 方法使用
  • Java 是经过值传递, 在第6行, 会在foo() 栈中建立一个对Object 对象的新的引用
  • 在第7行 , 一个string 类型的对象被建立, 此时 会在foo() 栈内存中建立它的一个引用 str
  • foo() 方法在第8行执行完毕, 此时, 程序会释放stack 栈内存中为foo() 方法分配的栈内存空间
  • 在第9行, main() 方法执行完毕, 为main()方法建立的堆栈内存被销毁, 此时 这个java 程序结束运行, Java Runtime 会释放全部的内存

 
三: Java Heap Difference with Stack Memory Space

基于上述的说明, 能够很容易的总结出堆栈内存的如下差别

1, 堆内存属于java 应用程序所使用, 栈内存属于线程所私有的, 它的生命周期与线程相同2, 不论什么时候建立一个对象, 它老是存储在堆内存空间 而且栈内存空间包含对它的引用 . 栈内存空间只包含方法原始数据类型局部变量以及堆空间中对象的引用变量3, 在堆中的对象能够全局访问, 栈内存空间属于线程所私有4, jvm 栈内存结构管理较为简单, 遵循LIFO 的原则, 堆空间内存管理较为复杂 , 细分为:新生代和老年代 etc..5, 栈内存生命周期短暂, 而堆内存伴随整个用用程序的生命周期6, 两者抛出异常的方式, 若是线程请求的栈深度大于虚拟机所容许的深度,将抛出StackOverflowError异常, 堆内存抛出OutOfMemoryError异常

相关文章
相关标签/搜索