Java堆内存和栈内存
Java堆内存和栈内存
概述:Java把内存分成两种,一种叫做栈内存,一种叫做堆内存
栈:
简单理解:堆栈(stack)是操作系统在建立某个进程或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有先进后出的特性。
特点:存取速度比堆要快,仅次于直接位于CPU中的寄存器。栈中的数据可以共享(意思是:栈中的数据可以被多个变量共同引用)。
缺点:存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。
相关存放对象:1一些基本类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄【例如:在函数中定义的一些基本类型的变量和对象的引用变量】。2方法的形参 直接在栈空间分配,当方法调用完成后从栈空间回收。
特殊:1方法的引用参数,在栈空间分配一个地址空间,并指向堆空间的对象区,当方法调用完成后从栈空间回收。2局部变量new出来之后,在栈控件和堆空间中分配空间,当局部变量生命周期结束后,它的栈空间立刻被回收,它的堆空间等待GC回收。
堆:
简单理解:每个Java应用都唯一对应一个JVM实例,每一个JVM实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或者数组都放在这个堆中,并由应用所有的线程共享。Java中分配堆内存是自动初始化的,Java中所有对象的存储控件都是在堆中分配的,但这些对象的引用则是在栈中分配,也就是一般在建立一个对象时,堆和栈都会分配内存。
特点:可以动态地分配内存大小、比较灵活,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。
缺点:由于要在运行时动态分配内存,存取速度较慢。
主要存放:1由new创建的对象和数组 ;2this
特殊:引用数据类型(需要用new来创建),既在栈控件分配一个地址空间,又在堆空间分配对象的类变量。
堆和栈的比较
从通俗化的角度来说,堆是用来存放对象的,栈是用来存放执行程序的
在编程中,例如在C/C++中,所有的方法调用都是通过栈来进行的,所有的局部变量、形式参数也都是通过栈来分配内存的。使用的时候,根据栈的工作原理,从栈顶向上用即可,Stack Pointer会自动指引程序到存储位置,程序只需要进行存储即可。退出函数的时候,修改栈指针即可将栈中存储的内容销毁。这种模块速度最快,适合用户存储执行程序。但是应当注意的是,在进行内存分配是,比如为一个即将要调用的程序模块分配数据区时,应当实现知道这个所需数据区的大小,也就是说虽然分配工作是在运行程序的时候进行的,但是分配的大小是在运行程序之前就知道的,这个是编译时确定的,而不是运行时。
堆是应用程序在运行过程中请求操作系统给分配的内存,由于是操作系统管理的内存分配,所以在分配和销毁是都需要占用时间,因此堆的工作效率比较低。但是堆的优点在于,编译器不需要知道从堆中分配了多少的内存空间,也不需要知道存储的数据要在堆中停留多长的时间,这也就使得用堆来保存数据有着更大的灵活性。事实上,面向对象的多态性的实现,堆内存的分配必不可少,因为多态对象所需的数据区大小只有在运行时确定了对象以后才能知道。在java中,创建对象只需要使用new关键字即可,执行这些代码时,就会在堆中自动进行数据的保存。也就是因为这种灵活分配存储空间的特性,堆内存分配的工作效率不高。
区别:
1.最主要的区别就是栈内存用来存储局部变量和方法调用。
而堆内存用来存储Java中的对象。无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中。
独有还是共享
2.栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。
而堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。
3.如果栈内存没有可用的空间存储方法调用和局部变量,JVM会抛出java.lang.StackOverFlowError。
而如果是堆内存没有可用的空间存储生成的对象,JVM会抛出java.lang.OutOfMemoryError。
4.栈的内存要远远小于堆内存,如果你使用递归的话,那么你的栈很快就会充满。如果递归没有及时跳出,很可能发生StackOverFlowError问题。
你可以通过-Xss选项设置栈内存的大小。-Xms选项可以设置堆的开始时的大小,-Xmx选项可以设置堆的最大值。
JAVA/269.html">http://www.itemperor.com/a/JAVA/269.html
原文链接:http://www.jxszl.com/biancheng/JAVA/446621.html