【Java面试题1】简单说说JVM堆的内存结构和GC回收流程

简介: 【Java面试题1】简单说说JVM堆的内存结构和GC回收流程

【Java面试题1】简单说说JVM堆的内存结构和GC回收流程


文章目录

前言

JVM堆内存结构简述

JVM堆内存结构图

堆初体验

结构详情

新生代

老年代

永久代/元空间

GC回收流程

GC回收流程图

GC回收详细流程

查看JDK自带可视化堆空间图

总结


前言

我们在Java面试中,只要是2年以上经验,一定会问你一下关于JVM方面的问题。开发两年时间不能对JVM没有了解,如果你还不了解,说明你的学习与探索能力不高,不能给到应有的加分项哦!小编也是最近刚刚开始学习,总结一下最近的学习成果。方便以后看,也希望小伙伴们看到可以帮助到您!


JVM堆内存结构简述

JVM堆内存结构图

堆初体验

所有的对象实例以及数组都要在堆上分配,堆是垃圾收集器管理的主要区域,也被称为“GC 堆”,也是我们优化最多考虑的地方。因为在一个项目中,会不断地创建对象,都是在堆里创建,如果一直不回收就会导致OOM,我们听的最多的情况哈!还有经常说的JVM调优,也是对堆进行参数优化配置,达到最接近理想状态。

结构详情

新生代

大部分刚创建的对象首先都是放在年轻代,新生代内存按照 8:1:1 的比例分为一个 Eden 和两个 Survivor(Survivor from,Survivor to)。

1. Eden 空间

Eden空间:主要是存放刚刚创建的新对象,如果可以Eden空间充足,新对象直接存放在Eden中,如果对象过大,放不下则会触发 Minor GC(效率很快)

2. Survivor 空间

每次执行Minor GC,会将Eden区中存活的对象放到Survivor的From区,而在From区中,仍存活的对象会根据他们的年龄值来决定去向,逃过一次Minor GC年龄加1,默认年数为15,就要到老年区。(From Survivor和To Survivor的逻辑关系会在GC时发生颠倒: From变To , To变From,目的是保证有连续的空间存放对方,避免碎片化的发生,后面GC流程在详细说)


老年代

在新生代中经历了 N 次(默认15次)垃圾回收后仍然存活的对象,就会被放到年老代中。年老代中存放的都是一些生命周期较长的对象。当老年代内存满时触发 Major GC 即 Full GC,Full GC 发生频率比较低,执行时间也是Minor GC的十倍以上。在老年代的对象一般为:存活时间比较长的,还有就是比较大的对象。


永久代/元空间

Java8 以前永久代,受JVM 管理,java8 以后元空间,直接使用物理内存。元空间位于堆外,所以它的最大内存大小取决于系统内存,而不是堆大小,我们可以指定 MaxMetaspaceSize 参数来限定它的最大内存。

GC回收流程

GC回收流程图

Java8 以前永久代,受JVM 管理

GC回收详细流程

当一个新对象创建时,首先会来到新生区的Eden区中,这里进行第一次判断:判断当前新对象是否可以再Eden区放得下,如果放下我们直接放到Eden区分配内存即可;如果放不下时,就要进行一次Minor GC。此次GC我们展开来详细说一下:回收时进行第二次判断:判断Survivor0是否放得下,如果放得下Eden 区存活对象复制到一个 Survivor0 区,然后清空 Eden 区,当这个 Survivor0 区也存放满了时,则将 Eden 区和 Survivor0 区存活对象复制到另一个 Survivor1 区,然后清空 Eden 和这个 Survivor0 区,此时 Survivor0 区是空的,然后将 Survivor0 区和 Survivor1 区交换,即保持 Survivor1 区为空, 如此往复(对照上面两个区域来回切换)。当对象在 Survivor 区躲过一次 GC 的话,其对象年龄便会加 1,此时进行第三次判断:判断年龄是否达到阈值,默认情况下,如果对象年龄达到 15 岁。超过就会移动到老年代中。不超则继续在Survivor。(对照上图虚线框)

执行完Minor GC后,进行第四次判断:判断Eden区是否放得下,如果放得下就进行内存分配,如果放不下默认作为大对象放到老年区。此时进行第五次判断新对象是否在老年区放得下,如果放得下就进行内存分配;如果放不下则进行一次Major GC 即 Full GC(执行时间为Minor GC的10倍多),最后进行第五次判断:判断老年区是否放得下,如果放得下进行内存分配;放不下则直接报异常OOM,此时需要改变堆的内存大小了。


-Xmx:最大堆大小

-Xms:初始堆大小


查看JDK自带可视化堆空间图

1. Win + R 输入jvisualvm

GC回收详细流程

当一个新对象创建时,首先会来到新生区的Eden区中,这里进行第一次判断:判断当前新对象是否可以再Eden区放得下,如果放下我们直接放到Eden区分配内存即可;如果放不下时,就要进行一次Minor GC。此次GC我们展开来详细说一下:回收时进行第二次判断:判断Survivor0是否放得下,如果放得下Eden 区存活对象复制到一个 Survivor0 区,然后清空 Eden 区,当这个 Survivor0 区也存放满了时,则将 Eden 区和 Survivor0 区存活对象复制到另一个 Survivor1 区,然后清空 Eden 和这个 Survivor0 区,此时 Survivor0 区是空的,然后将 Survivor0 区和 Survivor1 区交换,即保持 Survivor1 区为空, 如此往复(对照上面两个区域来回切换)。当对象在 Survivor 区躲过一次 GC 的话,其对象年龄便会加 1,此时进行第三次判断:判断年龄是否达到阈值,默认情况下,如果对象年龄达到 15 岁。超过就会移动到老年代中。不超则继续在Survivor。(对照上图虚线框)

执行完Minor GC后,进行第四次判断:判断Eden区是否放得下,如果放得下就进行内存分配,如果放不下默认作为大对象放到老年区。此时进行第五次判断新对象是否在老年区放得下,如果放得下就进行内存分配;如果放不下则进行一次Major GC 即 Full GC(执行时间为Minor GC的10倍多),最后进行第五次判断:判断老年区是否放得下,如果放得下进行内存分配;放不下则直接报异常OOM,此时需要改变堆的内存大小了。


-Xmx:最大堆大小

-Xms:初始堆大小


查看JDK自带可视化堆空间图

1. Win + R 输入jvisualvm

2. 安装GC插件

JVM监控工具jvisualvm的使用及GC插件安装

3. 查看内存图

总结

这样一个大的面试题就描述完成了,主要是理解GC回收的流程懂了,堆的结构也就知道怎么回事了。

相关文章
|
1天前
|
存储 Java 编译器
Java内存模型(JMM)深度解析####
本文深入探讨了Java内存模型(JMM)的工作原理,旨在帮助开发者理解多线程环境下并发编程的挑战与解决方案。通过剖析JVM如何管理线程间的数据可见性、原子性和有序性问题,本文将揭示synchronized关键字背后的机制,并介绍volatile关键字和final关键字在保证变量同步与不可变性方面的作用。同时,文章还将讨论现代Java并发工具类如java.util.concurrent包中的核心组件,以及它们如何简化高效并发程序的设计。无论你是初学者还是有经验的开发者,本文都将为你提供宝贵的见解,助你在Java并发编程领域更进一步。 ####
|
1天前
|
存储 安全 Java
什么是 Java 的内存模型?
Java内存模型(Java Memory Model, JMM)是Java虚拟机(JVM)规范的一部分,它定义了一套规则,用于指导Java程序中变量的访问和内存交互方式。
8 1
|
7天前
|
存储 运维 Java
💻Java零基础:深入了解Java内存机制
【10月更文挑战第18天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
21 1
|
10天前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。
|
10天前
|
监控 安全 Java
Java Z 垃圾收集器如何彻底改变内存管理
大家好,我是V哥。今天聊聊Java的ZGC(Z Garbage Collector)。ZGC是一个低延迟垃圾收集器,专为大内存应用场景设计。其核心优势包括:极低的暂停时间(通常低于10毫秒)、支持TB级内存、使用着色指针实现高效对象管理、并发压缩和去碎片化、不分代的内存管理。适用于实时数据分析、高性能服务器和在线交易系统等场景,能显著提升应用的性能和稳定性。如何启用?只需在JVM启动参数中加入`-XX:+UseZGC`即可。
134 0
|
3月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
324 0
|
9天前
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
19 1
|
14天前
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。
|
18天前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。
|
23天前
|
存储 编译器
数据在内存中的存储
数据在内存中的存储
37 4