-
2021-02-12 15:56:39
一、概述
在Java中,内存分为两种,一种是栈内存,另一种就是堆内存。
二、堆内存
1、什么是堆内存?
堆内存是Java内存中的一种,它的作用是用于存储Java中的对象和数组,当我们new一个对象或者创建一个数组的时候,就会在堆内存中开辟一段空间给它,用于存放。
2、堆内存的特点是什么?
第一点:堆其实可以类似的看做是管道,或者说是平时去排队买票的的情况差不多,所以堆内存的特点就是:先进先出,后进后出,也就是你先排队,好,你先买票。
第二点:堆可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,但缺点是,由于要在运行时动态分配内存,存取速度较慢。
3、new对象在堆中如何分配?
由Java虚拟机的自动垃圾回收器来管理。
三、栈内存
1、什么是栈内存
栈内存是Java的另一种内存,主要是用来执行程序用的,比如:基本类型的变量和对象的引用变量。
2、栈内存的特点
第一点:栈内存就好像一个矿泉水瓶,像里面放入东西,那么先放入的沉入底部,所以它的特点是:先进后出,后进先出
第二点:存取速度比堆要快,仅次于寄存器,栈数据可以共享,但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性
3、栈内存分配机制
栈内存可以称为一级缓存,由垃圾回收器自动回收
4、数据共享
例子:
int a = 3;
int b = 3;
第一步处理:
1.编译器先处理int a = 3;
2.创建变量a的引用
3.在栈中查找是否有3这个值
4.没有找到,将3存放,a指向3
第二步处理:
1.处理b=3
2.创建变量b的引用
3.找到,直接赋值
第三步改变:
接下来
a = 4;
同上方法
a的值改变,a指向4,b的值是不会发生改变的。
PS:如果是两个对象的话,那就不一样了,对象指向的是同一个引用,一个发生改变,另一个也会发生改变。
四、栈和堆的区别
JVM是基于堆栈的虚拟机,JVM为每个新创建的线程都分配一个堆栈。也就是说,对于一个Java程序来说,它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。
差异点:
1.堆内存用来存放由new创建的对象和数组。
2.栈内存用来存放方法或者局部变量等。
3.堆是先进先出,后进后出。
4.栈是后进先出,先进后出。
相同点:
1.都是属于Java内存的一种。
2.系统都会自动去回收它,但是对于堆内存一般开发人员会自动回收它。
以上就是本次整理的全部相关知识点,感谢大家的学习和对脚本之家的支持。
更多相关内容 -
java 中堆内存和栈内存理解
2020-08-31 06:16:49主要介绍了java 中的堆内存和栈内存的知识,有需要的朋友可以参考下 -
Java中堆内存和栈内存详解.doc
2021-09-30 23:25:09Java中堆内存和栈内存详解.doc -
Java中堆内存和栈内存详解
2014-02-28 13:45:32详细的讲解了java内存分配,包括运行时堆和栈内存的分配,变量和方法存储等 -
简述JAVA中堆内存与栈内存的区别
2020-08-18 19:33:52主要介绍了JAVA中堆内存与栈内存的区别,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下 -
java中栈内存和堆内存有什么区别
2021-03-09 08:53:56栈内存和堆内存的区别:1、栈内存用来存放基本类型的变量和引用变量,堆内存用来存储java中的对象,无论是成员变量,局部变量,还是类变量,他们指向的对象都存储在堆内存中。(视频教程推荐:java视频)2、栈内存归属...栈内存和堆内存的区别:
1、栈内存用来存放基本类型的变量和引用变量,堆内存用来存储java中的对象,无论是成员变量,局部变量,还是类变量,他们指向的对象都存储在堆内存中。
(视频教程推荐:java视频)
2、栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属的线程中可见,即栈内存可以理解成线程的私有内存;堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。
3、如果栈内存没有可用的空间存储方法调用和局部变量,JVM会抛出java.lang.stackoverflowerror 错误;如果是堆内存内有可用的空间存储生成的对象,jvm会抛出java.lang.outofmemoryerror错误。
3、栈的内存要远远小于堆内存,如果你使用递归的话,那么你的栈会很快充满。-Xss设置每个线程堆栈内存的大小 -Xms可以设置堆内存开始时的大小。
总结:
JVM 中堆和栈属于不同的内存区域,使用目的也不同。栈常用于保存方法帧和局部变量,而对象总是在堆上分配。栈通常都比堆小,也不会在多个线程之间共享,而堆被整个 JVM 的所有线程共享。
-
浅谈Java栈内存和堆内存
2022-03-22 10:22:50在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存...介绍Java语言有关内存分配的知识。Java语言把内存分为两种:
栈内存
和堆内存
。栈内存
在方法中定义的一些
基本类型的变量
和对象的引用变量
都在方法的栈内存中分配,当在一段代码块中定义一个变量时,Java就在栈内存中为这个变量分配内存空间,当超出变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立刻被另作他用。
堆内存
堆内存用来存放由
new
运算符创建的数组或对象
,在堆中分配的内存,由Java虚拟机的垃圾回收器来自动管理。在堆中创建了一个数组或对象后,同时还在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,引用变量实际上保存的是数组或对象在堆内存中的首地址(也称为对象的句柄),以后就可以在程序中使用栈的引用变量来访问堆中的数组或对象。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。引用变量就相当于是为数组或对象起的一个名称。而数组或对象本身在堆内存中分配,即使程序运行到使用
new
运算符创建数组或对象的语句所在的代码块之外,数组或对象本身所占据的内存也不会被释放,数组或对象在没有引用变量指向它时,会变为垃圾,不能再被使用,但仍然占据内存空间不放,在随后一个不确定的时间被垃圾回收器收走(释放掉),这也是Java比较占内存的原因。Java有一个特殊的引用型常量
null
,如果将一个引用变量赋值为null
,则表示该引用变量不指向(引用)任何对象。
下面通过一个数组案例进行演示,以对栈内存和堆内存有更深的了解。
一维数组是最简单的数组,其逻辑结构是线性表。要使用一维数组,需要先声明数组;分配空间;创建数组元素并赋值。
数据类型 [] 数组名; //声明一维数组 数组名 = new 数据类型[个数]; //分配内存给数组
在数组的声明格式里,“数据类型”是声明数组元素的数据类型,可以是Java语言中任意的数据类型,包括基本类型和引用类型。
与C/C++语言不同,Java语言在数组的定义中并不为数组元素分配内存,因此
“[]”
中不用给出数组中元素的个数(即数组的长度),但必须在为它分配内存空间后才可使用。数组声明之后,接下来就要分配数组所需的内存,这时必须用运算符
new
,利用new
运算符为数组元素分配内存空间的方式称为动态内存分配方式
。int [] x; //声明名称为x的int型数组 x = new int[10]; //x数组中包含有10个元素,并为这10元素分配内存空间
在声明数组时,也可以将两个语句合并成一行,格式如下:
数据类型 [] 数组名 = new 数据类型[个数]; int [] x = new int[10];
等号左边的
“int [] x ”
相当于定义了一个特殊的变量x,x的数据类型是一个对int
型数组对象的引用,x就是一个数组的引用变量,其引用的数组元素个数不定。等号右边的“new int[10]”
就是在堆内存中创建一个具有10个int型变量的数组对象。其意义就是将右边的数组对象赋值给左边的数组引用变量。这里我们先声明一个数组,例如:
int [] x; //定义了一个数组x
这条语句执行完成后的内存状态如图下所示。
这时只声明了数组,而没有对其分配内存空间。现在我们为数组元素分配内存空间。
x = new int[10]; //初始化数组
这条语句执行完后的内存状态如图下所示。
声明数组并分配相应的内存空间,引用变量指向数组对象
执行
“x=new int[10];”
后,在堆内存里创建了一个数组对象,为这个数组对象分配了10个整数单元,并将数组对象赋给了数组引用变量x。引用变量就相当于C语言中的指针变量,而数组对象就是指针变量指向的那个内存块。所以在Java内部还是有指针,只是把指针的概念对用户隐藏起来了,而用户所使用的是引用变量。用户也可以改变x的值,让它指向另外一个数组对象,或者不指向任何数组对象。要想让x不指向任何数组对象,只需要将常量
null
赋给x即可。如执行“x = null;”
语句后的内存状态如图下所示。执行完
“x = null;”
语句后,原来通过new int[10]产生的数组对象不再被任何引用变量所引用,变成了所谓的“垃圾”,直到垃圾回收器来将它释放掉。
感谢大家的耐心阅读,如有建议请私信或评论留言
-
详解Java的堆内存与栈内存的存储机制
2020-09-02 23:45:28主要介绍了Java的堆内存与栈内存的存储机制,包括JVM的内存优化和GC等相关方面内容,需要的朋友可以参考下 -
Java堆内存和栈内存
2020-12-22 15:22:30在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存... -
java堆内存和栈内存的区别
2018-04-22 17:02:11总结:1 栈:为编译器自动分配和释放,如函数参数、局部变量、临时变量等等2 堆:为成员分配和释放,由程序员自己申请、自己释放。...Java堆内存堆内存在Java运行时被使用来为对象和JRE类分配内存。不论什...总结:
1 栈:为编译器自动分配和释放,如函数参数、局部变量、临时变量等等
2 堆:为成员分配和释放,由程序员自己申请、自己释放。否则发生内存泄露。典型为使用new申请的堆内容。
除了这两部分,还有一部分是:
3 静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。
Java堆内存
堆内存在Java运行时被使用来为对象和JRE类分配内存。不论什么时候我们创建了对象,它将一直会在堆内存上创建。垃圾回收运行在堆内存上来释放没有任何引用的对象所占的内存,任何在堆上被创建的对象都有一个全局的访问,并且可以在应用的任何位置被引用。Java栈内存
Java的栈内存被用来线程的执行,他们包含生命周期很短的具体值的方法和在堆中使用这个方法对象的引用。栈内存是LIFO(后进先出)序列。当方法被调用的时候,堆内存中一个新的块被创建,保存了本地原始值和在方法中对其他对象的引用。这个方法结束之后,这个块对其他方法就变成可用的了。栈内存与堆内存相比是非常小的。我们用下边的例子理解堆内存和栈内存- package com.journaldev.test;
- public class Memory {
- public static void main(String[] args) { // Line 1
- 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
- }
下边的图片展示了上边程序堆和栈内存的引用,并且是怎么用来存储原始值、对象和变量的引用。
我们来看看程序执行的过程: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),和堆内存相比栈内存非常快。
原文地址:http://www.journaldev.com/4098/java-heap-memory-vs-stack-memory-difference
-
Java中堆内存与栈内存分配浅析
2011-11-02 15:53:09本文分析了Java中堆内存与栈内存分配的异同 -
java中栈内存与堆内存(JVM内存模型)
2021-03-14 18:16:23java中栈内存与堆内存(JVM内存模型)Java中堆内存和栈内存详解1 和 Java中堆内存和栈内存详解2 都粗略讲解了栈内存和堆内存的区别,以及代码中哪些变量存储在堆中、哪些存储在栈中。内存中的堆和栈到底是什么 详细... -
Java 堆内存与栈内存详细介绍
2020-09-01 07:35:05主要介绍了Java 堆内存与栈内存详细介绍的相关资料,这里对java 的堆内存和栈内存进行了详细的分析,需要的朋友可以参考下 -
Java中堆内存和栈内存有什么区别
2018-05-19 23:17:26Java把内存分成两种,一种叫做栈内存,一种叫做堆内存在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过... -
浅析Java堆内存和栈内存的区别
2018-03-06 09:36:55参考 堆内存:https://baike.baidu.com/item/%E5%A0%86%E5%86%85%E5%AD%98/7270805?fr=aladdin ...Java把内存划分成两种:一种是栈内存,一种是堆内存。 一、栈内存 存放基本类型的变量,对象的引用和方... -
Java中栈内存和堆内存详解
2013-04-27 09:26:01Java中栈内存和堆内存详解,非常容易理解 -
彻底理解Java中堆和栈
2021-06-14 09:19:41堆内存是java内存中的一种,它的作用是用于存储java中的对象和数组,当我们new一个对象或者创建一个数组的时候,就会在堆内存中开辟一段空间给它,用于存放。 堆内存的特点是什么? 第一点:堆其实可以类似的看做是... -
堆内存和栈内存的区别
2020-08-08 21:30:07首先要分清栈内存和数据结构中的栈——例如java.util.Stack。 栈内存是内存中用来存储数据的一部分空间,而Stack是一种先进后出的线性表。 堆内存和栈内存的区别 java中堆和栈的区别自然是面试中的常见问题,下面几... -
Java 堆和栈的区别
2021-03-05 14:56:361、概述在Java中,内存分为两种,一种是栈内存,另一种就是堆内存。2、堆内存1.什么是堆内存?1堆内存是是Java内存中的一种,它的作用是用于存储Java中的对象和数组,当我们new一个对象或者创建一个数组的时候,就会... -
java中堆栈内存分析(二)让你彻底明白JAVA中堆与栈的区别(详细)
2019-03-09 15:47:52在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存... -
java内存溢出示例(堆溢出、栈溢出)
2020-09-04 11:39:00主要介绍了java内存溢出示例(堆溢出、栈溢出),需要的朋友可以参考下 -
JAVA之堆内存和栈内存的区别
2018-01-25 12:30:45Java把内存分成两种,一种叫做栈内存,一种叫做堆内存在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过... -
Java中的栈和堆
2021-03-16 15:05:44这里浅谈Java中的栈和堆首先,将结论写在前面,后面再用例子加以验证。Java的栈中存储以下类型数据,栈对应的英文单词是Stack基本类型引用类型变量方法栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享...