学习Java,肯定会接触到栈和堆,刚入门的小伙伴难免会有些疑惑,栈和堆区别在哪里?由于所有的Java程序都运行在JVM虚拟机内部,小华君今天就跟大家说一说JVM内存中的栈和堆的区别。

java堆和栈的主要区别(每天学Java栈和堆的区别)(1)

要了解栈和堆的区别,自然我们首先要看看什么是栈和堆。

栈(stack))是为执行线程留出的内存空间。JVM规范让每个Java线程拥有自己的独立的JVM栈,也就是Java方法的调用栈。同时JVM规范为了允许native代码可以调用Java代码,以及允许Java代码调用native方法,还规定每个Java线程拥有自己的独立的native方法栈。这俩都是JVM规范所规定的概念上的东西,并不是说具体的JVM实现真的要给每个Java线程开两个独立的栈。事实上,每个Java线程其实只有一个调用栈,融合了JVM规范的JVM栈与native方法栈这俩概念。

堆(heap)是用于存放Java对象的内存区域,Java对象全部都在堆上。但是,这个“堆”并不是数据意义上的堆,而是动态内存分配意义上的堆——用于管理动态生命周期的内存区域。JVM的堆被同一个JVM实例中的所有Java线程共享。也就是说,每一个线程都有一个栈,但是每一个应用程序通常只有一个堆。

我们接下来再来看栈和堆的区别。

其实小华君刚刚已经说出来了一点了,就是关于独享还是共享的。栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。而堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。

第二点,栈和堆最主要的区别就是各自的职能。栈内存用来存储局部变量和方法调用。当函数被调用的时候,栈顶为局部变量和一些 bookkeeping 数据预留块。当函数执行完毕,块就没有用了,可能在下次的函数调用的时候再被使用。栈通常用后进先出(LIFO)的方式预留空间;因此最近的保留块(reserved block)通常最先被释放。这么做可以使跟踪堆栈变的简单;从栈中释放块(free block)只不过是指针的偏移而已。

而堆内存用来存储Java中的对象。无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中。和栈不一样,从堆上分配和重新分配块没有固定模式;可以在任何时候分配和释放它。这样使得跟踪哪部分堆已经被分配和被释放变的异常复杂;有许多定制的堆分配策略用来为不同的使用模式下调整堆的性能。

在空间大小上,栈的内存要远远小于堆内存。栈是连续的内存块,栈的大小设置是在线程被创建的时候。可以通过-Xss选项设置栈内存的大小。如果你在编译之前就明确知道你需要的分配数据大小,并且并不是太大,可以使用栈。而堆的大小设置是在应用程序启动的时候,正常情况下不需要担心它的实际大小。如果在运行期间你不知道会需要多大的数据或者你需要分配大量的内存,建议你使用堆。

在垃圾回收上,堆是由Java的垃圾回收机制来负责处理的。由于堆是动态分配内存大小,垃圾收集器可以自动回收不再使用的内存空间。栈相较而言更难回收,一般不回收。

其余的,像是在速度、异常错误上,栈和堆也都还有一定的区别。小华君就不一一列举了。

好了,今天小华君就说到这里。依然是欢迎大牛补充和指正的。如果你想更好更快更系统地学习Java,小华君建议你来北京华信智原实地了解或者试听一节课。毕竟这里的老师都是行业的一线项目经理,专业技能扎实,项目经验丰富,会带领你通过企业的真实项目案例来学习。

,