空间分配

java程序中变量空间的分配主要集中在三个内存区域:静态内存、栈和堆。栈用于存放基本类型的变量。基本类型是java语言兼顾效率而保留的。他们以自动变量的形式存储。栈中也可以存放对象的reference,但是决不能存放对象本身。堆是Java最主要的空间分配方式,他用以存放所有的java对象。java使用new关键字在堆上动态的分配内存空间。java中的堆栈由java自己管理,对程序员是透明的。静态存储空间用于存放被声明为static的变量,可以存放对象的reference但是不能存放对象本身,这一点和栈是一样的。另外还有一块常量存储空间用于存放程序中的常量。java还包含一类特殊的non-ram存储空间。数据完全活动于程序之外的,即使程序不继续执行,这些数据也仍然存在。这主要包括流对象和持久化对象。

在c++中,全局变量和静态变量在静态内存区分配空间;自动变量和局部变量在栈中分配空间;而用new关键字声明的对象在堆中分配空间;c++中也有一个常量存储空间。静态内存和栈中的变量编译器会决定其生存期,并自动消灭之。和Java不同的是,c++中的对象可以存储在栈中,例如直接声明、没有使用关键字new的对象,这样的对象会自动调用默认构造函数,在栈中分配空间。这种情况下对象一定要有默认的构造函数,否则会报错。而堆中的变量即用new来定义的对象要程序员手动消灭。这也是c++中一个比较头疼的问题。所以在c++中new关键字的使用要比较谨慎,并不是如java中逢对象即new的。

堆和栈是两种基本的数据结构。但是,栈是机器系统提供的数据结构,现代的计算机都在底层提供对栈结构的支持。计算机有专门的寄存器指向栈地址,也拥有直接对栈进行操作的机器指令。因此,在栈中操作的效率很高,但是支持的数据类型也很有限。栈的高效率特点使得它的使用频率很高。函数调用是栈使用的一个典型例子。程序在调用函数的时候,将返回地址压栈,然后跳转至所调用函数的地址。函数调用完毕,将返回地址弹栈,返回主程序。栈中存放的变量在编译期就必须知道他们的大小和存活时间。在c/c++中,可以使用alloca对栈进行动态分配,当然不鼓励使用。

栈有一个有趣的特性即它的共享。例如定义两个变量:int a = 3; int b = 3;编译器会先创建一个变量为a 的引用,然后查找有没有内容为3的地址。如果没有就分配空间存放整形数3,同时将a指向它。在处理b变量的定义是,由于现在栈中已经有了3这个数,便将b直接指向3所在地址。这种机制和reference不同。当a,b中有一个变化时不会影响另外一个。例如执行a=4语句。首先系统会在栈中查找有没有现存的4,如果有即将a指向这个地址,否则会分配一个新的空间存放4,然后指向这个新地址。

堆结构一般是由特定语言的库实现的。如c语言中的malloc,free等就是对堆结构进行管理维护的函数。当程序获得新的内存空间时,首先试图从内部堆中寻找可用的内存空间,如果没有可以使用的内存空间,则试图利用系统调用来动态增加程序数据段的内存大小,新分配得到的空间首先被组织进内部堆中去,然后再以适当的形式返回给调用者。当程序释放分配的内存空间时,这片内存空间被返回内部堆结构中,可能会被适当的处理(比如和其他空闲空间合并成更大的空闲空间),以更适合下一次内存分配申请。这套复杂的分配机制实际上相当于一个内存分配的缓冲池(Cache)。

java中外覆类的定义有点复杂。以String为例:关于String str = "abc"的内部工作。Java内部将此语句转化为以下几个步骤:
  (1)先定义一个名为str的对String类的对象引用变量:String str;
  (2)在栈中查找有没有存放值为"abc"的地址,如果没有,则开辟一个存放字面值为"abc"的地址,接着创建一个新的String类的对象o,并将o的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象o。如果已经有了值为"abc"的地址,则查找对象o,并返回o的地址。
  (3)将str指向对象o的地址。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值