《JVM由浅入深学习【六】 2024-01-10》JVM由简入深学习提升分享

简介: 《JVM由浅入深学习【六】 2024-01-10》JVM由简入深学习提升分享

1.jvm堆内存分代模型

介绍一下JVM中堆的垃圾回收过程

当Java应用程序运行时,它在堆内存中分为新生代(Young Generation)、老年代(Old Generation)和持久代(Permanent Generation,Java 8之后被元数据区替代)等几个区域。新生代主要用于存放新创建的对象,而垃圾回收主要集中在新生代进行。

堆的结构

  1. 新生代(Young Generation):包括三个区域,Eden空间和两个Survivor空间(通常命名为S0和S1)。对象首先在Eden空间分配,经过一轮Minor GC 后如果仍然存活,则会被移到Survivor空间,经过多次(minor15次,cms收集器默认6次)后会晋升到老年代。当然可以自己设置次数,下面是官方文档
    **注意:**即使对象的年龄尚未达到设定的阈值,如果Survivor区中的空间占用超过50%,这些对象也可能被提前晋升到老年代。这是因为为了避免Survivor区溢出,JVM可能会进行提前晋升。
    结论–>动态年龄判断: Survivor 区的对象年龄从小到大进行累加,当累加到 X 年龄 (某个年龄)时占用空间的总和大于50% (可以使用-XX:TargetSurvivorRatio=? 来设置保留多少空闲空间,默认值是 50) ,那么比 X 年龄大的对象都会晋升到老年代 3. 这两个可以查看垃圾回收器默认值
  2. 老年代(Old Generation):用于存放生命周期较长的对象,经过多次Minor GC(15次的s区域来回回收,这里次数也称为年龄,即15岁进入到老年代)或者经过一次Full GC后的对象会晋升到这个区域。
  3. 持久代(Permanent Generation):在Java 7及之前,主要用于存放类的元数据信息,包括类的结构、方法等。在Java 8及之后,被元数据区替代。

新生代的垃圾回收流程

新生代的垃圾回收主要分为两个阶段:Minor GC和Full GC。

1. Minor GC
  • 触发条件: 当Eden空间满时触发Minor GC。
  • 回收过程:
  • 首先,垃圾回收器标记并清理Eden空间中不再被引用的对象。
  • 存活的对象会被移到Survivor空间,如果Survivor空间满,将会晋升到老年代。
  • 清理后,Eden空间变为新的工作区域,等待下一次的对象分配。
  • 特点:
  • Minor GC的速度较快,因为它只需要清理新生代,而且很多对象在新生代很快被回收。
2. Full GC
  • 触发条件: 在老年代空间不足时触发Full GC。或者是由于Minor GC过程中晋升到老年代的平均大小大于老年代的剩余空间时。
  • 回收过程:
  • Full GC会对整个堆进行清理,包括新生代和老年代。
  • 它会停止应用程序的所有线程,进行垃圾回收,因此 Full GC 的耗时较长。
  • 对象的引用关系被重新整理,不再被引用的对象所回收。
  • 特点:
  • Full GC对整个堆进行回收,包括新生代和老年代,速度较慢。
总结

新生代的垃圾回收主要通过Minor GC来清理Eden空间和Survivor空间,快速回收短时间内创建的对象。而Full GC则是针对整个堆内存进行的,较为耗时。这种分代垃圾回收的策略有效提高了垃圾回收的效率,延长了老年代的垃圾回收触发时间,提高了整体的应用程序性能。

什么是老年代空间分配担保机制

  1. 老年代空间分配担保机制是Java虚拟机为了避免由于新生代Minor GC导致的空间不足而触发一次Full GC,从而提高垃圾回收效率的一种机制。具体而言,它保证了在发生Minor GC时,虚拟机在老年代预留一定的内存空间,以应对新生代对象晋升到老年代的情况。
  2. 这个机制的设计基于这样一个考虑:在一次Minor GC之前,虚拟机会首先检查老年代的剩余空间是否大于新生代所有对象的总空间,如果是,那么Minor GC可以放心进行。如果不足以容纳新生代所有对象,那么虚拟机会查看老年代中的存活对象是否能够在某个特定的年龄阈值之下就能被全部安置到老年代,如果这个条件成立,同样触发Minor GC,否则,进行一次Full GC。
  3. 这个担保机制的核心思想是为了尽量避免因为新生代对象晋升导致的Full GC。因为Minor GC的频率通常比Full GC低得多,而且Minor GC的速度更快,因此通过老年代空间分配担保机制,可以在大多数情况下避免因为新生代GC而触发Full GC,提高了垃圾回收的效率。

什么情况下对象会进入老年代?

躲过 15 次 GC之后进入老年代,可通过JVM 参数“-XX:MaxTenuringThreshold”来设 置年龄,默认为 15 岁

2、动态对象年龄判断

3、老年代空间担保机制

4、大对象直接进入老年代

  • 大对象是指需要大量连续内存空间的 Java 对象,比如很长的字符串或者是很大的数组或者List 集合,大对象在分配空间时,容易导致内存明明还有不少空间时就提前触发垃圾回收以获得足够的连续空间来存放它们,而当复制对象时,大对象又会引起高额的内存复制开销,为了避免新生代里出现那些大对象,然后屡次躲过 GC 而进行来回复制,此时JVM 就直接把该大对象放入老年代,而不会经过新生代;
  • 我们可以通过JVM 参数“-XX:PretenureSizeThreshold”设置多大的对象直接进入老年代,该值为字节数,比如“1048576”字节就是 1MB,该参数表示如果创建一个大于这个大小的对象,比如一个超大的数组或者 List 集合,此时就直接把该大对象放入老年代,而不会经过新生代-XX:PretenureSizeThreshold 参数只对 Serial 和 ParNew 两款新生代收集器有效,其他新生代垃圾收售器不支持该参数,如果必须使用此参数讲行调优,可考虑 ParNew+CMS 的收集器组合。

JVM 运行时数据区 元空间的特点及作用?

  • 1、在JDK1.8 开始才出现元空间的概念,之前叫方法区/永久代
  • 2、元空间与 Java 堆类似,是线程共享的内存区域
  • 3、存储被加载的类信息、常量、静态变量、常量池、即时编译后的代码等数据
  • 4、元空间采用的是本地内存,本地内存有多少剩余空间,它就能扩展到多大空间,也可以设置元空间大小;
    -XX:MetaspaceSize=20M -XX:MaxMetaspaceSize=20m
  • 5、元空间很少有 GC 垃圾收集,一般该区域回收条件苛刻,能回收的信息比较少,所以 GC很少来回收

结语:

在Java中,垃圾回收是一项重要的技术,通过自动管理内存资源,使得开发者可以更专注于业务逻辑的实现而不用过多关心内存的分配和释放。通过深入理解垃圾回收机制,我们可以更好地优化代码,提高程序性能,确保系统的稳定性和可维护性。

感谢您的阅读,希望本文对您理解和应用Java中的垃圾回收机制有所帮助。如果有任何疑问或建议,欢迎留言交流,共同学习进步。谢谢!

public class BlogEnding {
    public static void main(String[] args) {
        encourageEngagement();
    }
    public static void encourageEngagement() {
        System.out.println("🚀 感谢您阅读本文!如果您觉得有收获,请一键三连:点赞 ❤️️、转发 🔁、评论 💬,并加关注哦!");
    }
}
相关文章
|
3月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
140 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
3月前
|
存储 SQL 小程序
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
这篇文章详细介绍了Java虚拟机(JVM)的运行时数据区域和JVM指令集,包括程序计数器、虚拟机栈、本地方法栈、直接内存、方法区和堆,以及栈帧的组成部分和执行流程。
53 2
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
|
7月前
|
缓存 Java
《JVM由浅入深学习九】 2024-01-15》JVM由简入深学习提升分(生产项目内存飙升分析)
《JVM由浅入深学习九】 2024-01-15》JVM由简入深学习提升分(生产项目内存飙升分析)
62 0
|
3月前
|
Java 应用服务中间件 程序员
JVM知识体系学习八:OOM的案例(承接上篇博文,可以作为面试中的案例)
这篇文章通过多个案例深入探讨了Java虚拟机(JVM)中的内存溢出问题,涵盖了堆内存、方法区、直接内存和栈内存溢出的原因、诊断方法和解决方案,并讨论了不同JDK版本垃圾回收器的变化。
51 4
|
3月前
|
Arthas 监控 Java
JVM知识体系学习七:了解JVM常用命令行参数、GC日志详解、调优三大方面(JVM规划和预调优、优化JVM环境、JVM运行出现的各种问题)、Arthas
这篇文章全面介绍了JVM的命令行参数、GC日志分析以及性能调优的各个方面,包括监控工具使用和实际案例分析。
130 3
|
3月前
|
SQL 缓存 Java
JVM知识体系学习三:class文件初始化过程、硬件层数据一致性(硬件层)、缓存行、指令乱序执行问题、如何保证不乱序(volatile等)
这篇文章详细介绍了JVM中类文件的初始化过程、硬件层面的数据一致性问题、缓存行和伪共享、指令乱序执行问题,以及如何通过`volatile`关键字和`synchronized`关键字来保证数据的有序性和可见性。
46 3
|
3月前
|
缓存 前端开发 Java
JVM知识体系学习二:ClassLoader 类加载器、类加载器层次、类过载过程之双亲委派机制、类加载范围、自定义类加载器、编译器、懒加载模式、打破双亲委派机制
这篇文章详细介绍了JVM中ClassLoader的工作原理,包括类加载器的层次结构、双亲委派机制、类加载过程、自定义类加载器的实现,以及如何打破双亲委派机制来实现热部署等功能。
113 3
|
3月前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
72 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
3月前
|
小程序 Oracle Java
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
这篇文章是关于JVM基础知识的介绍,包括JVM的跨平台和跨语言特性、Class文件格式的详细解析,以及如何使用javap和jclasslib工具来分析Class文件。
68 0
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
|
7月前
|
存储 缓存 NoSQL
Redis系列学习文章分享---第十三篇(Redis多级缓存--JVM进程缓存+Lua语法)
Redis系列学习文章分享---第十三篇(Redis多级缓存--JVM进程缓存+Lua语法)
88 1