简述JAVA中堆内存与栈内存的区别

 更新时间:2020年07月18日 10:23:58   作者:zsq_fengchen  
这篇文章主要介绍了JAVA中堆内存与栈内存的区别,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下

Java把内存划分成两种:一种是栈内存,一种是堆内存

一、栈内存

      存放基本类型的变量,对象的引用和方法调用,遵循先入后出的原则。
      栈内存在函数中定义的“一些基本类型的变量和对象的引用变量”都在函数的栈内存中分配。当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。

        Java中的代码是在函数体中执行的,每个函数主体都会被放在栈内存中,比如main函数。假如main函数里调用了其他的函数,比如add(),那么在栈里面的的存储就是最底层是main,mian上面是add。栈的运行时后入先出的,所以会执行时会先销毁add,再销毁main。

        栈的优势是,栈内存与堆内存相比是非常小的,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(int, short, long, byte, float, double, boolean, char)和对象句柄。栈有一个很重要的特殊性,就是存在栈中的数据可以共享。

二、堆内存

     存放所有new出来的对象和数组

     特此强调,堆内存和数据结构中的堆完全是两码事,分配方式倒是类似于链表

     堆内存是区别于栈区、全局数据区和代码区的另一个内存区域。堆允许程序在运行时动态地申请某个大小的内存空间,堆内存实际上指的就是(满足堆内存性质的)优先队列的一种数据结构,第1个元素有最高的优先权。

      在堆内存分配时首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。

       另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。堆内存是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆内存的大小受限于计算机系统中有效的虚拟内存。由此可见,堆内存获得的空间比较灵活,也比较大。堆内存是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便。

       栈与堆都是Java用来在Ram中存放数据的地方。与C ++不同,Java自动管理栈和堆,程序员不能直接设置栈或堆

       Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过新的,newarray,anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。

三、其他数据存储

    1、常量池:存放基本类型常量和字符串常量(public static final)
    2、静态域:存放静态成员(static定义的)
    3、非RAM存储:硬盘等永久存储空间

堆内存和栈内存的区别:

   1、应用程序所有的部分都使用堆内存,然后栈内存通过一个线程运行来使用。
   2、不论对象什么时候创建,他都会存储在堆内存中,栈内存包含它的引用。栈内存只包含原始值变量好和堆中对象变量的引用。
   3、存储在堆中的对象是全局可以被访问的,然而栈内存不能被其他线程所访问。
   4、栈中的内存管理使用LIFO的方式完成,而堆内存的管理要更复杂了,因为它是全局被访问的。
   5、栈内存是生命周期很短的,然而堆内存的生命周期从程序的运行开始到运行结束。
   6、我们可以使用-Xms和-Xmx JVM选项定义开始的大小和堆内存的最大值,我们可以使用-Xss定义栈的大小
   7、当栈内存满的时候,Java抛出java.lang.StackOverFlowError异常而堆内存满的时候抛出java.lang.OutOfMemoryError: Java Heap Space错误
   8、和堆内存比,栈内存要小的多,因为明确使用了内存分配规则(LIFO),和堆内存相比栈内存非常快。

总结:

   1 栈:为编译器自动分配和释放,如函数参数、局部变量、临时变量等等

   2 堆:为成员分配和释放,由程序员自己申请、自己释放。否则发生内存泄露。典型为使用new申请的堆内容。
        除了这两部分,还有一部分是:

   3 静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。

以上就是简述JAVA中堆内存与栈内存的区别的详细内容,更多关于JAVA中堆内存与栈内存的资料请关注脚本之家其它相关文章!

相关文章

  • Struts 2中的constant配置详解

    Struts 2中的constant配置详解

    通过对这些属性的配置,可以改变Struts 2 框架的一些默认行为,这些配置可以在struts.xml文件中完成,也可以在struts.properties文件中完成
    2016-09-09
  • Java使用join方法暂停当前线程

    Java使用join方法暂停当前线程

    这篇文章主要为大家详细介绍了Java使用join方法暂停当前线程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • JDBC三层架构深入刨析

    JDBC三层架构深入刨析

    三层架构是一种软件设计架构,是一种组织代码的手段和方法,三层架构的优点是扩展性好,复用性高;缺点是步骤多,比较繁琐;代码多,效率降低
    2022-12-12
  • SpringBoot集成ffmpeg实现视频转码播放示例详解

    SpringBoot集成ffmpeg实现视频转码播放示例详解

    这篇文章主要为大家介绍了SpringBoot集成ffmpeg实现视频转码播放示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • java追加写入txt文件的方法总结

    java追加写入txt文件的方法总结

    在本篇文章里我们给大家整理了关于java如何追加写入txt文件的方法和代码,需要的朋友们可以参考下。
    2020-02-02
  • Java 整合模板彻底解决ssm配置难题

    Java 整合模板彻底解决ssm配置难题

    SSM框架是spring MVC ,spring和mybatis框架的整合,是标准的MVC模式,将整个系统划分为表现层,controller层,service层,DAO层四层,使用spring MVC负责请求的转发和视图管理,spring实现业务对象管理,mybatis作为数据对象的持久化引擎
    2021-10-10
  • 解决Spring AOP拦截抽象类(父类)中方法失效问题

    解决Spring AOP拦截抽象类(父类)中方法失效问题

    这篇文章主要介绍了解决Spring AOP拦截抽象类(父类)中方法失效问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • SpringBoot整合JPA方法及配置解析

    SpringBoot整合JPA方法及配置解析

    这篇文章主要介绍了SpringBoot整合JPA方法及配置过程,JPA是Java Persistence API的简称,中文名Java持久层API,感兴趣想要详细了解可以参考下文
    2023-05-05
  • 如何利用JConsole观察分析Java程序的运行并进行排错调优

    如何利用JConsole观察分析Java程序的运行并进行排错调优

    从Java 5开始 引入了 JConsole。JConsole 是一个内置 Java 性能分析器,可以从命令行或在 GUI shell 中运行。您可以轻松地使用 JConsole(或者,它更高端的 “近亲” VisualVM )来监控 Java 应用程序性能和跟踪 Java 中的代码
    2015-12-12
  • RabbitMQ 最常用的三大模式实例解析

    RabbitMQ 最常用的三大模式实例解析

    这篇文章主要介绍了RabbitMQ 最常用的三大模式实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12

最新评论