Java 堆栈

java中的堆和栈

Java把内存区域划分成两种:一种是栈内存,一种是堆内存。至于“方法区”(静态存储区),可以理解为:主要存放静态数、全局static数据和常量。这块内存在程序编译时就已经分配好,并且在程序政哥哥运行期间都存在。总的来说:堆和栈针对非静态数据,而方法区针对静态数据。

一、堆内存和栈内存

栈(stack)与堆(heap)都是java用来在RAM(随机存取存储器 Random-Access Memory)中存放数据的地方,与C++不同,java自动管理栈和堆,程序员不能直接地设置栈和堆。

  • 简单理解:栈(stack)是操作系统建立在某个进程或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有先进后出的特点。
    特点:存取速度比堆要快,仅次于直接位于CPU中的寄存器。栈中的数据可以共享(意思是:栈中的数据可以被多个变量共同引用)。
    缺点:存在栈中的数据大小与生存周期必须是确定的,缺乏灵活性。
    相关存储对象:1.一些基类型的变量(boolean,byte,short,char,int,long,float,double)和对象语柄【例如:在函数中定义的一些基本类型的变量和对象的引用变量】。2.方法的形参 直接在栈空间分配,当方法调用完成后从栈空间回收。
    特殊:1.方法的引用参数 ,在栈空间分配一个地址空间,并指向堆空间的对象区,当方法调用完成后从栈空间回收 2.局部变量new出来之后,在栈空间可堆空间分配空间,当局部变量生命周期结束后,它的栈空间立刻被回收,它的堆空间等待GC回收。


  • 简单理解 :每个Java应用实例都唯一对应一个JVM实例,每一个JVM实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或者数组都放在这个堆中,并由应用所有的线程共享。Java中分配堆内存是自动初始化的,Java中所有对象的存储空间都是在堆中分配的,但这些对象的引用则是在栈中分配,也就是一般在建立一个对象时,堆和栈都会分配内存。
    特点:可以动态地分配内存大小、比较灵活、生存周期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。
    缺点:由于要在运行时动态分配内存,存取速度较慢。
    主要存放:1.由new创建的对象和数组 2.this
    特殊:引用数据类型(需要用new来创建),即在栈空间分配一个地址空间,又在堆空间分配对象的类变量。
    补充:在堆中产生了一个对象或数组后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。
    引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。

引用变量是普通变量,定义时在栈中分配内存,引用变量在程序运行到作用域外释放。而数组和对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句所在的代码块之外,数组和对象本身占用的内存也不会被释放,数组和对象在没有引用便利的指向他的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉。这个也是java比较占内存的主要原因。

这里可以理解为 :

String  s1=new String"abc");

这里面:“abc”表示栈中的一个存储空间中的一个数据,new String(“abc”)表示存在于堆中的一个对象,这个对象的值为“abc”,String s1则表示栈中定义的一个取了new String(“abc”)在堆中的首地址的一个特殊变量,也就是:s1成了引用变量,相当于一个别名。

二、Java数据存储和JVM内存划分

在Java中,有六个不同的地方可以存储数据:

1、寄存器(register) : 这是最快的存储区,因为他位于不同于其他存储区的地方———处理器内部。但是寄存器的数量及其有限,所以存储器由编译器根据需求进行分配。你不能直接控制,也不能在程序中感觉到寄存器存在的任何迹象。
2、堆栈(stack) : 位于通用RAM中,单通过他的“堆栈指针”可以从处理器获得支持。堆栈指针若向下移动,则分配新内存;若向上移动,则释放那些内存。这是一种快速有效的分配存储方法,仅次于寄存器。创建程序的时候,JAVA编译器必须知道存储在堆栈内所有数据的确切大小和生命周期,因为它必须生成相应的代码,以便上下移动堆栈指针,这一约束限制了程序的灵活性,所以虽然某些Java数据存储在堆栈中—–特别是引用对象,但是JAVA对象不存储其中。
3、堆(heap) : 一种通用性的内存池(也存在于RAM中),用于存放所有的JAVA对象。堆不同于栈的好处是:编译器不需要知道要从堆里分配多少存储区域,也不必知道存储的数据在堆里存货多长时间。因此,在堆里分配存储又很大的灵活性。当需要创建一个对象的时候,只需要new写一行简单的代码,当执行这行代码时,会自动在堆里进行存储分配。淡然,为这种灵活性必须要付出相应的代码。用堆进行存储分配比用栈进行存储需要更多的时间。
4、静态存储(static storage) : 这里的“静态”是指“在固定的位置”。静态存储里存放程序运行时一直存在的数据。你可用关键字static来标识一个对象的特定元素使静态的,单JAVA对象本身从来不会存放在静态存储空间里。
5、常量存储(constant storage) : 常量值通常直接存放在程序代码内部,这样做是安全的,因为它们永远不会被改变。有时,在嵌入式系统中,常量本身会和其他部分分割离开,所以在这种情况下,可以选择将其放在ROM中。
6、非RAM存储 : 如果数据万村存活于程序之外,那么它可以不受任何程序的任何控制,在程序没有运行时也可以存在。

JVM的内存区分
JVM可以分为三个:堆(heap)、栈(stack)和方法区(method)。

1、堆区
存储的全是对象,每个对象都包含一个与之对应的class信息(我们常说的类类型,通过Class.getClass()等方式获取),class目的是得到操作指令。
JVM只有一个堆区被所有的线程共享,堆中不存放基本类型和对象引用,只存放对象本身。
2、栈区
每个线程包含自己的一个栈区,栈中只保存基本数据类型的对象和自定义对象的引用。
每个栈中的数据(基本类型和对象引用)都是私有的,其他栈不可访问。
栈=基本类型变量区+执行环境上下文+操作指令区(存放操作指令)
3、方法区
又称为“静态区”,和堆一样,被所有的线程共享。
方法区包含所有的class和static变量。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值