前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >原来JVM中的堆栈TM这么简单!

原来JVM中的堆栈TM这么简单!

作者头像
ImportSource
发布2018-04-03 15:34:07
1.4K0
发布2018-04-03 15:34:07
举报
文章被收录于专栏:ImportSourceImportSource

二话不说先上图!

好,也许你已经懂了,如果想更懂,请看今天的正文!


以下是正文:

也许你会在网上查询到很多有关栈啊,堆啊的很多内容,或者一些java ee的书上或者一些教程里。但似乎很少有一个对于stack和heap的完整的详细的解释。

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。

Memory.java 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 vs Heap Memory的全部内容,希望这篇文章能够帮到你。有什么问题欢迎在评论区讨论。


附:以下是我在网上找到的一些图片,让你对stack和heap有更直观的印象。

Stack : – local variables Heap : – instance variables – static variables – objects

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-05-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ImportSource 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档