JVM 堆与栈

这里写图片描述

Java Heap Memory

      堆内存(heap memory)是被用来在runtime的时候给对象和jre的那些class分配内存的。注意是runtime的时候。不管你何时创建对象,创建任何一个对象,这些对象都是被创建在了heap空间里的。那个我们熟悉的gc(垃圾回收站)负责把那些不再被引用(reference)的对象从heap memory中清理掉,这也是gc的职责所在。在heap空间里创建的任何对象都是全局访问的。可以被应用程序的任何地方引用。

Java Stack Memory

      java里的stack内存(stack memory)是被用来线程的执行的。也就是stack是线程级别的。而heap是对象级别的。这个stack里边包含了方法里边那些定义的值,这些值随着一次方法执行完毕后就消失了;还包含了引用地址。这个引用地址就是对存放在heap memory中的一个链接。你可以理解为关系数据库里边的外键,nosql中的外链。总之你理解就行。stack memory由于她是个stack结构。所以呢,他也遵循LIFO,就是后进先出的顺序。一个方法不论什么时候被调用,一个针对该方法的全新的block就会在stack memory里被创建,用来存储这个方法里的本地基本类型的值以及这个方法对其他对象的引用地址。一旦方法执行结束,这个block的状态就变为unused了,就是变为了空闲状态,就变为available了。宣布单身了,等着下一个method来用她。stack memory的size相比heap memory的size要小得多。

      现在就让我们上一个simple program来更好的理解一下堆栈memory。

public class Memory {
    public static void main(String[] args) { // Line1
        int i = 1; // Line 2
        Object obj = new Object(); // Line 3
        Memory mem = new Memory(); // 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
}

      下面这个图就展示了在上面这个程序中的stack和heap memory的存储和引用关系。堆栈怎么被用来存储基本类型值(primitive value)以及对象以及对象的引用。
这里写图片描述

接下来我们就一步步的来看上面的那个program的执行情况。

  • 一旦我们运行了这个程序,它就会把所有的runtime class load 到 heap空间。当main()方法在line1那个地方被发现后,Java Runtime就会创建stack memory给main()方法这个线程来用。

  • 在line2那个地方,我们创建了一个primitive(基本类型)的局部变量,这个变量自然是被存储到了main()的stack memory里的。

  • 在line3那个位置,我们创建了一个对象,按照前面说的,这个对象自然是存储在heap memory里边的,并且在stack memory里边也有个这个对象的引用地址被存储了进去。line4的对象创建过程和line3是一样的。

  • 现在我们来到了line5这个地方,这一行我们调用了foo()方法,这时候一个block在stack的顶部被创建,这个block现在专门为foo()方法服务。由于java是按值传递,所以在line6那个位置一个新的对象引用就会在foo() 方法的stack block中被创建。

  • 在line7那个位置,一个字符串被创建,这个串是在heap空间的string池(String Pool)中。并且对这个string对象的引用自然也在foo()方法的stack空间里被创建了。

  • 在line8那个地方foo()方法就被终止了,在方法结束的时候,在stack中为foo()分配的那个block重新变回空窗期,宣布available了。

  • 在line9那个地方,main()方法也要结束了。自然为main()创建的stack memory就会被destory掉了。自此,Java Runtime 释放所有的memory然后结束程序的执行!

heap memory与stack memory的区别

基于上面的那一堆解释,我们现在可以很轻松的总结出以下不同之处:

1、heap用在一个application的很多地方,但stack memory只用于一个线程的执行。前者是对象级别,后者是线程级别。

2、只要是对象的创建,都是被存储到heap space中,同时stack中有这个对象的引用地址。stack memory中只包含基本类型变量和存储在heap space中的对象的引用变量。

3、 存储在heap中的对象是全局都可以访问的,然而stack memory不能被其他线程访问。

4、stack 的内存管理是使用LIFO的,然而heap的内存管理要更复杂,因为heap是被全局使用的。因此heap memory被分为Young-Generation,Old-Generation等等,有关这个你可以去了解下java的gc(垃圾回收)机制。

5、 stack memory是短命的,然而heap memory则是application运行的整个生命周期都有他,直到application结束掉。

6、我们使用-Xms和-Xmx jam 参数来定义heap memory的启动size和最大size。stack memory的size则是使用-Xss。

7、当stack memory满了,那么Java runtime就会抛出一个java.lang.StackOverFlowError的异常。当heap memory 满了,则会抛出java.lang.OutOfMemoryError: Java Heap Space error.

8、stack memory相比heap memory来说是非常小的。另外由于内存分配比较简单(LIFO),stack memory相比heap memory来说是非常快的。

其他

Stack :

  • local variables

Heap :

  • instance variables
  • static variables
  • objects

这里写图片描述

这里写图片描述

原文地址:http://mp.weixin.qq.com/s/lVgrYh2jRBqUnSLnjUaAjg

个人微信公众号:
这里写图片描述

作者:jiankunking 出处:http://blog.csdn.net/jiankunking

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值