JVM中的堆内存和栈内存

一、了解堆和栈

        JVM是基于堆栈的虚拟机,堆栈是一种数据结构,是用来存储数据的。对于一个java程序来说,它的运行用就是通过对堆栈的操作完成的。

         栈内存用于存储局部变量,以及对象的引用,它是一个连续的内在空间,由系统自动分配,也就是说栈空间的分配和回收是由系统来做的,我们不需要手动控制。它的性能较高,栈内存具有先进后出、后进先出的特点,虚拟机会为每条线程创建一个虚拟机栈,当执行方法时,虚拟机会创建出该方法的一个栈帧,该方法中所有的局部变量都会存储到这个栈帧中,方法执行完毕后,栈帧弹栈。栈内存使用完毕后立即释放,生命值相对较短。

         堆内存用于存储引用类型的数据,主要是对象和数组及字符串。全局只有一个堆内存,所有的线程共用一个堆内存。在堆中产生一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。引用变量就相当于为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量访问堆中的数组或对象了。使用后,等待JVM收取垃圾,生命值相对较长。

 二、栈内存的优缺点

         优点:对于栈内存,当一个函数调用时,系统就会为该函数的调用分配栈空间,当函数返回后,系统就会自动回收这块空间,同理,下次其它函数调用和返回,系统还是会自动分配和回收空间。线程安全,因为栈内存是线程独立的。

         栈空间的大小是固定的,它有一个水位线,标识栈空间的分配状态,水位线里面的表示已经分配,然后这个水位线会根据函数调用和返回的情况自动调整。因此,栈空间的分配和回收非常简单,只需要调整水位线位置就可以了,没有任何多余操作。 

          缺点:存在栈中的数据大小与生存期必须是确定的,缺乏灵活性,快捷,但是自由度小。

三、堆内存的优缺点

         优点:堆内存是区别于栈区、全局数据区和代码区的另一个内存区域。堆允许程序在运行时动态地申请某个大小的内存空间,自由度大,大小不固定,可以动态扩容。

         缺点:

(1)C语言中常用的malloc()函数和new()函数分配的内存就是堆内存,堆内存容易产生内存泄露,比如malloc()出来的如果没有free()new()出来的如果没有delete(),都会产生内存泄露。

(2)堆内存容易产生内存碎片,在分配和回收时需要对很多内存碎片进行整理,效率较低,因此要有很多自定义的内存分配器,但它依旧没有栈空间分配回收速度快。

(3)线程不安全,它不像栈内存是线程独立的,堆内存可以被一个进程内所有的线程访问,多线程操作就容易产生问题。

 四、堆内存和栈内存的示例

         

         

         上图程序的运行结果中,num1和 num2没有交换成功,而数组中索引为1和2位置却交换成功了,这可以从堆内存和栈内存的分析中推断出原因。

        num1 和 num2是基本数据类且是局部变量,只会存储在栈帧中。由于Java中只有值传递,所以exchange 栈帧和栈帧中的num1和 num2是完全不同的两个变量,exchange 栈帧中发生的交换是成功的是对main 栈帧中的两个变量不会造成影响。

         而arr是引用类型,数据实际上存储在堆内存中,main 栈帧中存储的是它的地址,作为0x1000。而Java 中只有值传递,因此main栈帧中的arr和exchange 栈帧中的arr值都是0×1000,但它们也是不同的两个变量。只不过引用类型数据操作比较特殊,是地址找到堆内存中对应的数据进行操作,而main栈帧与exchange 栈帧公用同一个堆内存,因此在exchange 中对堆内存进行的更改,在main栈帧中也可以感知到。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值