Java中堆和栈的区别详解

当一个人开始学习Java或者其他编程语言的时候,会接触到堆和栈,由于一开始没有明确清晰的说明解释,很多人会产生很多疑问,什么是堆,什么是栈,堆和栈有什么区别?更糟糕的是,Java中存在栈这样一个后进先出(Last In First Out)的顺序的数据结构,这就是java.util.Stack。这种情况下,不免让很多人更加费解前面的问题。事实上,堆和栈都是内存中的一部分,有着不同的作用,而且一个程序需要在这片区域上分配内存。众所周知,所有的Java程序都运行在JVM虚拟机内部,我们这里介绍的自然是JVM(虚拟)内存中的堆和栈。

区别

java中堆和栈的区别自然是面试中的常见问题,下面几点就是其具体的区别

各司其职

最主要的区别就是栈内存用来存储局部变量和方法调用。
而堆内存用来存储Java中的对象。无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中。

独有还是共享

栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。
而堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。

异常错误

如果栈内存没有可用的空间存储方法调用和局部变量,JVM会抛出java.lang.StackOverFlowError。
而如果是堆内存没有可用的空间存储生成的对象,JVM会抛出java.lang.OutOfMemoryError。

空间大小

栈的内存要远远小于堆内存,如果你使用递归的话,那么你的栈很快就会充满。如果递归没有及时跳出,很可能发生StackOverFlowError问题。
你可以通过-Xss选项设置栈内存的大小。-Xms选项可以设置堆的开始时的大小,-Xmx选项可以设置堆的最大值。

这就是Java中堆和栈的区别。理解好这个问题的话,可以对你解决开发中的问题,分析堆内存和栈内存使用,甚至性能调优都有帮助。

查看默认值(Updated)

查看堆的默认值,使用下面的代码,其中InitialHeapSize为最开始的堆的大小,MaxHeapSize为堆的最大值。

代码如下:

13:17 $ java -XX:+PrintFlagsFinal -version | grep HeapSize
    uintx ErgoHeapSizeLimit                         = 0                                   {product}
    uintx HeapSizePerGCThread                       = 87241520                            {product}
    uintx InitialHeapSize                          := 134217728                           {product}
    uintx LargePageHeapSizeThreshold                = 134217728                           {product}
    uintx MaxHeapSize                              := 2147483648                          {product}
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

查看栈的默认值,其中ThreadStackSize为栈内存的大小。

代码如下:

13:21 $ java -XX:+PrintFlagsFinal -version | grep ThreadStackSize
     intx CompilerThreadStackSize                   = 0                                   {pd product}
     intx ThreadStackSize                           = 1024                                {pd product}
     intx VMThreadStackSize                         = 1024                                {pd product}
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

译文信息

原汁原味的英文原文:http://javarevisited.blogspot.com.au/2013/01/difference-between-stack-and-heap-java.html.

译文在原文基础上进行了修改,整理,删减。如有兴趣可以访问原文。P.S.地址已被墙。

(0)

相关推荐

  • 详谈java 堆区、方法区和栈区

    堆区:只存放类对象,线程共享: 方法区:又叫静态存储区,存放class文件和静态数据,线程共享; 栈区:存放方法局部变量,基本类型变量区.执行环境上下文.操作指令区,线程不共享; class A { private String a = "aa"; //a在堆区 public boolean methodB() { String b = "bb"; //b在栈区 final String c = "cc"; // c在栈区 } } 以上这篇详谈j

  • Java 堆内存与栈内存详细介绍

     Java 中的堆和栈 Java把内存划分成两种:一种是栈内存,一种是堆内存. ​ 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用. 堆内存用于存放由new创建的对象和数组.在堆中分配的内存,由java虚拟机自动垃圾回收器来管理.在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取

  • java 栈和堆区别详细介绍

    java 栈和堆区别 1, 垃圾回收机制仅仅作用于堆内存,与栈内存无关; 2, 栈:stack 栈的存取速度比堆快,效率高 保存局部变量和对象的引用值 3, 堆:保存较大的变量 4, 栈有一个很重要的特殊性,就是存在栈中的数据可以共享 编译器处理int a = 3 时,首先会在栈中创建一个变量为a的引用,然后查找栈中是否存在3这个值,如果不存在,就将3存放进来: 处理b = 3时,也是这样,因为之前将3存放进来了,所以此时编译器只需将创建b这个变量再指向3就行了(有利于节省空间). 这个时候就出

  • Java中堆和栈的区别详解

    当一个人开始学习Java或者其他编程语言的时候,会接触到堆和栈,由于一开始没有明确清晰的说明解释,很多人会产生很多疑问,什么是堆,什么是栈,堆和栈有什么区别?更糟糕的是,Java中存在栈这样一个后进先出(Last In First Out)的顺序的数据结构,这就是java.util.Stack.这种情况下,不免让很多人更加费解前面的问题.事实上,堆和栈都是内存中的一部分,有着不同的作用,而且一个程序需要在这片区域上分配内存.众所周知,所有的Java程序都运行在JVM虚拟机内部,我们这里介绍的自然

  • C/C++ 中堆和栈及静态数据区详解

    C/C++ 中堆和栈及静态数据区详解   五大内存分区 在C++中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和常量存储区.下面分别来介绍: 栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区.里面的变量通常是局部变量.函数参数等. 堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete.如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收. 自由存储区,就是那些由malloc等分

  • Java中Exception和Error的区别详解

    世界上存在永远不会出错的程序吗?也许这只会出现在程序员的梦中.随着编程语言和软件的诞生,异常情况就如影随形地纠缠着我们,只有正确的处理好意外情况,才能保证程序的可靠性. java语言在设计之初就提供了相对完善的异常处理机制,这也是java得以大行其道的原因之一,因为这种机制大大降低了编写和维护可靠程序的门槛.如今,异常处理机制已经成为现代编程语言的标配. 今天我要问你的问题是,请对比Exception和Error,另外,运行时异常与一般异常有什么区别? 典型回答 Exception和Error都

  • 基于Java中throw和throws的区别(详解)

    系统自动抛出的异常 所有系统定义的编译和运行异常都可以由系统自动抛出,称为标准异常,并且 Java 强烈地要求应用程序进行完整的异常处理,给用户友好的提示,或者修正后使程序继续执行. 语句抛出的异常 用户程序自定义的异常和应用程序特定的异常,必须借助于 throws 和 throw 语句来定义抛出异常. throw是语句抛出一个异常. 语法:throw (异常对象); throw e; throws是方法可能抛出异常的声明.(用在声明方法时,表示该方法可能要抛出异常) 语法:[(修饰符)](返回

  • Java中接口和抽象类的区别详解

    需求:接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承实体类(concrete class)?抽象类中是否可以有静态的main方法? 先说明二者的定义,然后聊聊需求,最后分析二者的区别. 含有abstract修饰符的类即为抽象类,抽象类不能创建实例对象.含有抽象方法的类必须定义为abstract class.在abstract class中,方法不必是抽象的,但是抽象方法必须在具体子类中实现,所以,不能有抽象构造方法或抽象静态方法.子类如果没有实现抽象父类中的所

  • java中ArrayList和LinkedList的区别详解

    ArrayList和LinkedList都实现了List接口,有以下的不同点: 1.ArrayList是基于索引的数据接口,它的底层是数组.它可以以O(1)时间复杂度对元素进行随机访问.与此对应,LinkedList是以元素列表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n). 2.相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者

  • Java 中泛型 T 和 ? 的区别详解

    目录 泛型中 T 类型变量 和 ? 通配符 区别 Generic Types 类型变量 用法 2.声明通用的方法 – 泛型方法: 有界类型参数 Wildcards 通配符 1.上界通配符:? extend 上界类型 2.无界通配符:? 3.下界通配符:? super 子类 类型擦除 泛型中 T 类型变量 和 ? 通配符 区别 定义不同 :T 是类型变量,? 是通配符 使用范围不同: ? 通配符用作 参数类型.字段类型.局部变量类型,有时作为返回类型(但请避免这样做) T 用作 声明类的类型参数.

  • java中堆和栈的区别分析

    堆和栈是Java数据结构里非常重要的概念,本文较为详细的分析了二者之间的区别.供大家参考.具体如下: Java的堆是一个运行时数据区,类的(对象从中分配空间.这些对象通过new.newarray.anewarray和multianewarray等 指令建立,它们不需要程序代码来显式的释放.堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时 动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据.但缺点是,由于要在运行时动态分配内存,存

  • Java中Vector与ArrayList的区别详解

    首先看这两类都实现List接口,而List接口一共有三个实现类,分别是ArrayList.Vector和LinkedList.List用于存放多个元素,能够维护元素的次序,并且允许元素的重复.3个具体实现类的相关区别如下:1.ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问.数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要讲已经有数组的数据复制到新的存储空间中.当从ArrayList的中间位置插入或者删除元素时,需要对数组

  • java中SynchronizedList和Vector的区别详解

    前言 Vector是java.util包中的一个类. SynchronizedList是java.util.Collections中的一个静态内部类. 在多线程的场景中可以直接使用Vector类,也可以使用Collections.synchronizedList(List list)方法来返回一个线程安全的List. 那么,到底SynchronizedList和Vector有没有区别,为什么java api要提供这两种线程安全的List的实现方式呢? 首先,我们知道Vector和Arraylis

随机推荐