java堆内存和栈内存的区别

原创 2018年04月17日 13:36:59

在Java中你会看到很多堆和栈内存的引用,JavaEE书和文章很难在程序的角度完全解释什么是堆什么是栈。


总结:
1 栈:为编译器自动分配和释放,如函数参数、局部变量、临时变量等等
2 堆:为成员分配和释放,由程序员自己申请、自己释放。否则发生内存泄露。典型为使用new申请的堆内容。
除了这两部分,还有一部分是:
3 静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。



Java堆内存

堆内存在Java运行时被使用来为对象和JRE类分配内存。不论什么时候我们创建了对象,它将一直会在堆内存上创建。垃圾回收运行在堆内存上来释放没有任何引用的对象所占的内存,任何在堆上被创建的对象都有一个全局的访问,并且可以在应用的任何位置被引用。

Java栈内存

Java的栈内存被用来线程的执行,他们包含生命周期很短的具体值的方法和在堆中使用这个方法对象的引用。栈内存是LIFO(后进先出)序列。当方法被调用的时候,堆内存中一个新的块被创建,保存了本地原始值和在方法中对其他对象的引用。这个方法结束之后,这个块对其他方法就变成可用的了。栈内存与堆内存相比是非常小的。
我们用下边的例子理解堆内存和栈内存
[java] view plain copy
  1. package com.journaldev.test;  
  2.    
  3. public class Memory {  
  4.    
  5.     public static void main(String[] args) { // Line 1  
  6.         int i=1// Line 2  
  7.         Object obj = new Object(); // Line 3  
  8.         Memory mem = new Memory(); // Line 4  
  9.         mem.foo(obj); // Line 5  
  10.     } // Line 9  
  11.    
  12.     private void foo(Object param) { // Line 6  
  13.         String str = param.toString(); //// Line 7  
  14.         System.out.println(str);  
  15.     } // Line 8  
  16.    
  17. }  

下边的图片展示了上边程序堆和栈内存的引用,并且是怎么用来存储原始值、对象和变量的引用。


我们来看看程序执行的过程:
1、只要我们一运行这个程序,它会加载所有的运行类到堆内存中去,当在第一行找到main()方法的时候,Java创建可以被main()方法线程使用的栈内存。
2、当在第一行,我们创建了本地原始变量,它在main()的栈中创建和保存。
3、因为我们在第三行创建了对象,它在堆内存中被创建,在栈内存中保存了它的引用,同样的过程也发生在第四行我们创建Memory对象的时候。
4、当在第五行我们调用foo()方法的时候,在堆的顶部创建了一个块来被foo()方法使用,因为Java是值传递的,在第六行一个新的对象的引用在foo()方法中的栈中被创建
5、在第七行一个String被创建,它在堆空间中的String池中运行,并且它的引用也在foo()方法的栈空间中被创建
6、foo()方法在第八行结束,此时在堆中为foo()方法分配的内存块可以被释放
7、在第九行,main()方法结束,栈为main()方法创建的内存空间可以被销毁。同样程序也在行结束,Java释放了所有的内存,结束了程序的运行

堆内存和栈内存的区别

基于上边的解释我们可以很简单的总结出堆和栈的区别:
1、应用程序所有的部分都使用堆内存,然后栈内存通过一个线程运行来使用。
2、不论对象什么时候创建,他都会存储在堆内存中,栈内存包含它的引用。栈内存只包含原始值变量好和堆中对象变量的引用。
3、存储在堆中的对象是全局可以被访问的,然而栈内存不能被其他线程所访问。
4、栈中的内存管理使用LIFO的方式完成,而堆内存的管理要更复杂了,因为它是全局被访问的。堆内存被分为,年轻一代,老一代等等,更多的细节请看,这篇文章
5、栈内存是生命周期很短的,然而堆内存的生命周期从程序的运行开始到运行结束。
6、我们可以使用-Xms和-Xmx JVM选项定义开始的大小和堆内存的最大值,我们可以使用-Xss定义栈的大小
7、当栈内存满的时候,Java抛出java.lang.StackOverFlowError异常而堆内存满的时候抛出java.lang.OutOfMemoryError: Java Heap Space错误
8、和堆内存比,栈内存要小的多,因为明确使用了内存分配规则(LIFO),和堆内存相比栈内存非常快。

JAVA之堆内存和栈内存的区别

笔者最近在准备面试的时候重新看了一些JAVA基础的知识,下面我们一起来看一下JAVA中堆栈内存的区别: Java把内存分成两种,一种叫做栈内存,一种叫做堆内存在函数中定义的一些基本类型的变量和对象的...
  • as02446418
  • as02446418
  • 2015-07-22 19:04:09
  • 2608

Java中栈内存、堆内存、方法区——浅析

引用自蛊惑Into博客园: Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时...
  • robinyin666
  • robinyin666
  • 2016-09-01 16:17:07
  • 612

js栈内存和堆内存的区别

首先JavaScript中的变量分为基本类型和引用类型。基本类型就是保存在栈内存中的简单数据段,而引用类型指的是那些保存在堆内存中的对象。 1、基本类型           基本类型有Unde...
  • zuiziyoudexiao
  • zuiziyoudexiao
  • 2017-06-08 20:27:32
  • 2202

JavaScript变量——栈内存or堆内存

堆和栈这两个字我们已经接触多很多次,那么具体是什么存在栈中什么存在堆中呢?就拿JavaScript中的变量来说:          首先JavaScript中的变量分为基本类型和引用类型。      ...
  • xdd19910505
  • xdd19910505
  • 2014-12-13 14:16:14
  • 8857

堆内存和栈内存详解.doc

  • 2011年09月24日 11:26
  • 30KB
  • 下载

JVM中堆内存和栈内存详解

Java中堆内存和栈内存详解 Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时...
  • zh521zh
  • zh521zh
  • 2015-07-23 18:21:11
  • 1956

JAVA面试、进阶必备——堆内存与栈内存

IT小修 2017-05-09 14:51 java堆栈 java面试过程中经常会被问到关于堆栈的问题,这里我稍微总结一下,供大家参考一下。 java的内存分为堆内存和栈内存 栈内存是指程序进...
  • u011277123
  • u011277123
  • 2017-05-10 18:21:22
  • 1092

javascript:栈内存与堆内存浅谈

javascript的栈内存与堆内存
  • HUSHILIN001
  • HUSHILIN001
  • 2017-08-03 23:23:19
  • 219

栈内存和堆内存之分.txt栈内存和堆内存之分.txt

  • 2011年04月26日 19:07
  • 558B
  • 下载

java虚拟机中栈内存与堆内存的区别

堆--用new建立,垃圾自动回收负责回收 1、堆是一个"运行时"数据区,类实例化的对象就是从堆上去分配空间的; 2、在堆上分配空间是通过"new"等指令建立的; 3、Java针对堆的操作和C++...
  • JameBing
  • JameBing
  • 2016-12-27 15:27:29
  • 1073
收藏助手
不良信息举报
您举报文章:java堆内存和栈内存的区别
举报原因:
原因补充:

(最多只允许输入30个字)