JAVA 栈内存和堆内存

来源:互联网 发布:nginx 配置证书链 编辑:程序博客网 时间:2024/06/07 12:40

java中栈内存指的是虚拟机栈,堆内存指的是java堆。

栈内存

栈内存,虚拟机栈。每个方法被执行的时候都会创建一个栈帧,用来存储局部变量,操作栈,动态链接,方法出口等信息。局部变量包括各种基本类型的变量和对象的引用变量都是在方法的栈内存中分配。其中8字节(64位)长度的double和long类型的数据占用2个局部变量的空间,其他数据类型只占用一个。局部变量所需要的空间是在编译期间完成的,当进入一个方法时候,这个方法所需的局部变量空间已经确定,在方法运行期间不会改变。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。当线程请求的栈深度大于虚拟机所允许的深度,则抛出StackOverflowError异常。当虚拟机栈无法扩展时候则抛出OutOfMemoryError异常。
这里牵涉到一个问题,就是为什么方法的执行会创建一个栈帧即在栈中操作而不是在堆中操作?
因为函数调用的局部状态之所以用栈来记录是因为这些数据的存活时间满足“后入先出”(LIFO)顺序,而栈的基本操作正好就是支持这种顺序的访问
如:

    public static void main(String args[]) {        a();    }    private static void a(){        b();    }    private static void b(){        c();    }    private static void c(){    }

实际实行的流程为

main()  a()  b()  c()   -                         main()   |   +>     -                    a()   .      |   .      +>   -                 b()   .      .    |   .      .    +>   -              c()   .      .    .    |   .      .    +   <-              return from c()   .      .    |   .      +   <-                 return from b()   .      |   +     <-                    return from a()   |   -                         return from main()

堆内存

堆内存在虚拟机启动的时候创建。堆内存的唯一目的就是创建对象实例。所有的对象实例和数组都在堆内存中分配。堆是由垃圾回收机制负责的,因此也叫做”GC堆”,java垃圾回收机制采用分代算法,堆由此分为新生代和老生代。堆的优势是可以动态的分配内存大小,生存期也不必实现高速编译器,因为它是运行时动态分配内存的,java的垃圾收集器会自动收走这些不再使用的数据。动态分配内存既是堆内存的优点,同时也是它的缺点,由于是动态分配所以存取速度比较慢。当堆内存满了无法扩展时就会抛出java.lang.OutOfMemoryError:Java heap space异常。

java内存还有:
这里写图片描述

1.程序计数器,(上图中的线程pc寄存器)记录当前线程所执行的字节码的行号。
2.本地方法栈,与上面的虚拟机栈类似,只不过虚拟机栈是为java方法服务,而本地方法栈是用来为native方法服务。
3.方法区,用于存放已被虚拟机加载的类信息、常量、静态变量。垃圾回收在这个区域出现的几率少。在这个区域的回收就是类型的卸载。只有当加载该类型的类加载器实例(非类加载器类型)为unreachable状态时,当前被加载的类型才被卸载。所以一般不会被卸载。
4.运行时常量池,存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放在方法区的运行时常量池中。该区域不会被回收,例如
String s=”abc”;
s=”xyz”;
s=null;
“abc”和”xyz”将一直存在于在字符串池中,这就是java内存泄露的原因之一。

参考文章:http://blog.csdn.net/dreamrealised/article/details/9123187

原创粉丝点击