当前位置: 首页 > news >正文

详解Java中的堆内存

详解Java中的堆内存

堆是JVM运行数据区中的一块内存空间,它是线程共享的一块区域(注意了!!!),主要用来保存数组和对象实例等(其实对象有时候是不在堆中进行分配的,想要了解的可以看我之前写的博文:小白秒懂什么是栈上分配)。在堆中内存空间不足以进行分配时,就会出现OutOfMemoryError(OOM)异常。

在JDK7和JDK8中,堆中的内存结构是不同的:
在这里插入图片描述

那在JDK8中的永久代(方法区)为什么没有了那?
它被移动到了本地内存中,被称为元空间

那又有一个疑问了:为什么要把堆内存中的永久代移动到本地内存中作为元空间?
其实就是为了避免OOM异常。

年轻代又被分为三部分:Eden区和两个Survivor区。两个Survivor区大小是完全相同的,被称为from区to区。Eden区和from区、to区的比例为8 : 1 : 1。

  1. 当有一个对象新创建后,其首先会被分配到Eden区(部分对象不会首先分配到Eden区,后面会说),当Eden区内存不足时,会标记Eden区中存活的对象,进行垃圾回收,并把存活的对象移动到from区。
  2. 当Eden区内存再次不足时,再次GC,把Eden区和from区中存活的对象通过复制算法移动到to区。
  3. 再次不足时,GC,通过复制算法将Eden区和to区中存活的对象移动到from区。
  4. 就这样一直移动,当一个对象移动了15次,就被将其分配到老年代。

这就是分代回收
但有些时候对象的除此创建并不会首先被分配到Eden区,这种对象就是大对象,也就是占用大量连续内存空间的对象,其会被直接分配到老年代。

这里可能大家还会有一个疑问:为什么对象移动了15次,就会将其分配给老年代?移动的次数又是存储在哪里的?

这里就又要说到对象的内存结构了。HotSpot虚拟机中,对象在内存中的存储被分为三个部分。如图:
在这里插入图片描述

对象头又被分为
在这里插入图片描述

在MarkWord中,就存储了对象的信息(下面只列了部分):

  1. age:对象分代年龄,占4位。
  2. hashcode。
  3. biased_lock:偏向锁标识,1位。(好奇什么是偏向锁的朋友,可以搜一下锁升级,也就是synchronized这个锁的知识,我这里不深入聊锁)
  4. 等等…

age就是我们对象的GC年龄,每次移动,都会加1。age占4位,也就是2^4 - 1 = 15。所以这就是分代年龄为什么是15次,因为它能存储的最大数值是15。

JVM也提供了参数去设置分代年龄的大小,但都不能超过15。

http://www.lryc.cn/news/454479.html

相关文章:

  • C++类和对象下详细指南
  • 【瑞昱RTL8763E】音频
  • videojs 播放监控
  • 电源管理芯片PMIC
  • C++ 线性表、内存操作、 迭代器,数据与算法分离。
  • PHP如何解析配置文件
  • 【Java】六大设计原则和23种设计模式
  • Java IO流全面教程
  • PCIe6.0 AIC金手指和板端CEM连接器信号完整性设计规范
  • 二、创建drf纯净项目
  • 算法1:双指针思想的运用(2)--C++
  • L1415 【哈工大_操作系统】CPU调度策略一个实际的schedule函数
  • 免费版U盘数据恢复软件大揭秘,拯救你的重要数据
  • Pikachu-Unsafe FileUpload-客户端check
  • 【数据结构】什么是红黑树(Red Black Tree)?
  • Xcode16适配
  • Vue - 路由用法
  • SpringBoot框架下校园资料库的构建与优化
  • vscode 连接云服务器(ubantu 20.04)
  • 【SpringBoot详细教程】-09-Redis详细教程以及SpringBoot整合Redis【持续更新】
  • 排序算法之——归并排序,计数排序
  • Linux中环境变量
  • 163页PPT罗兰贝格品牌战略升级:华为案例启示与电器集团转型之路
  • 系统设计,如何设计一个秒杀功能
  • Linux:进程入门(进程与程序的区别,进程的标识符,fork函数创建多进程)
  • 索尼MDR-M1:超宽频的音频盛宴,打造沉浸式音乐体验
  • 【Linux】线程的概念
  • centos7.9环境下mysql8数据库双机互备环境部署
  • git 报错git: ‘remote-https‘ is not a git command. See ‘git --help‘.
  • mysql学习教程,从入门到精通,SQL GROUP BY 子句(31)