JVM 如何理解新生区、永久区、堆内存调优? 柔情只为你懂 2024-03-17 10:28 32阅读 0赞 **目录** 一、新生区 二、永久区 三、堆内存调优 -------------------- ## 一、新生区 ## JVM的堆是Java内存管理的核心,它被用于存储对象和数组。堆被划分为两部分:新生代和老年代。本文将会介绍新生代的工作原理。 新生代是堆的一部分,其大小通常比老年代小得多。它主要用于存储那些短期存活的对象,通常包括刚被创建的对象以及在栈帧中已经不再使用的对象。由于这些对象往往具有较短的生命周期,因此在新生代中进行垃圾回收操作可以使得整个垃圾回收过程更加高效。 新生代被划分成三个部分:Eden区、Survivor0区和Survivor1区。每个新对象都被分配到Eden区,如果Eden区没有足够的空间,则会触发Minor GC(局部收集),这个过程会清理掉所有不再被引用的对象,并将剩余的对象移动到Survivor区。Survivor0与Survivor1用来交替地存放对象,在Minor GC时,存活的对象会被移动到另一个Survivor区,这样可以保证每个Survivor区只有一部分对象,可以减少复制的成本。当一个对象被多次复制后仍然存活下来,就会被移到老年代中。 由于新生代中的对象通常存活时间较短,所以需要经常进行垃圾回收。在HotSpot中,新生代的垃圾回收是由Parallel Scavenge收集器实现的。这个收集器使用了多线程并行复制算法,可以同时使用多个CPU来加速垃圾回收。其工作流程如下: 1. 将所有可达的对象标记为“保留” 2. 复制所有保留的对象到Survivor区 3. 清空Eden区,并将Survivor区里的对象复制到另一个Survivor区(如果存在) 4. 如果一个对象已经被复制过两次或以上,就会被移动到老年代中 Parallel Scavenge收集器的主要优点是它能够充分利用多核心CPU的优势,从而提高垃圾回收的效率。同时,由于它采用复制算法,因此不会产生内存碎片问题,这有利于程序的长期稳定性。 总之,新生代是JVM堆的重要组成部分。它的任务是存储那些短期存活的对象,并经常进行垃圾回收。在HotSpot中,新生代的垃圾回收是由Parallel Scavenge收集器实现的,这个收集器具有良好的性能和稳定性。 ![367bf1c32faa4c21ae08369d22a58b63.png][] -------------------- ## 二、永久区 ## 在JVM中,永久区(Permanent Generation)是一块特殊的内存区域,它用来保存类的相关信息。在Java8之前,永久区是Java虚拟机中的一个重要组成部分,在Java8之后,则被称为元数据区(Meta Space),并被移动到了本地内存中。 永久区主要包含以下内容: 1. 类的元数据信息:Java类在编译后会被转换成字节码,并且和其他类一起存放在JVM的永久区中。每个类都有自己的元数据信息,比如类名、父类名、接口、字段、方法等。 2. 字符串常量池:字符串常量池也存放在永久区中,它保存了所有的字符串常量,包括字面值和通过String类创建的字符串对象。 3. 静态变量:静态变量也被存放在永久区中,它们与类的元数据信息一样,只会在类加载时被初始化一次。 4. 常量池:常量池是指在Java代码中使用final关键字定义的常量,它们也被存放在永久区中。 由于永久区包含了大量的元数据信息,因此它对JVM的性能和稳定性非常重要。但是在早期版本的JVM中,永久区的大小是固定的,并且难以进行动态调整,因此会导致内存溢出等问题。为了解决这个问题,JVM引入了PermGen空间参数来控制永久区的大小,并在Java8中将元数据区移动到了本地内存中。 在Java8之后,永久区被替换成了元数据区(Meta Space),它也是一块专门用来存放类的相关信息的内存区域。与永久区不同的是,元数据区不再使用固定大小的内存,而是可以根据需要动态地分配内存。另外,元数据区也不再使用PermGen空间参数,而是使用了两个新的参数:MaxMetaspaceSize和MinMetaspaceFreeRatio,它们用于控制元数据区的最大和最小大小以及最小空闲比例。 总之,永久区(现在的元数据区)是JVM中非常重要的一部分,它保存了类的元数据信息、字符串常量池、静态变量和常量池等内容。在早期版本的JVM中,永久区的大小是固定的,难以进行动态调整,容易导致内存溢出等问题。为了解决这个问题,JVM引入了PermGen空间参数来控制永久区的大小,并在Java8中将元数据区移动到了本地内存中,可以动态分配内存,更加灵活。 ![a8eef159634a4aae881e4bec3ffe442a.png][] -------------------- ## 三、堆内存调优 ## JVM堆内存调优是Java应用程序性能优化的重要一环。在Java程序运行时,所有的对象都存放在堆内存中。因此,有效地管理和调优堆内存可以提高Java程序的性能和稳定性。 首先需要了解Java堆内存结构。 Java堆内存被划分为新生代和老年代两部分。新生代又被分为Eden区、Survivor0区和Survivor1区。新创建的对象会被分配到Eden区,如果Eden区没有足够的空间来存放对象,就会触发Minor GC(新生代垃圾回收)。在Minor GC过程中,存活的对象会被复制到Survivor区,而不存活的对象会被回收。当一个对象经过多次Minor GC后仍然存活,它就会被移到老年代。当老年代内存不足时,就会触发Full GC(整堆垃圾回收),这个过程开销比较大,应该尽量避免。 接下来,让我们看看如何调优Java堆内存: * 设置堆内存大小 默认情况下,Java虚拟机会自动设置堆内存大小。但是,这种方式可能并不适合所有的应用程序。通常情况下,推荐将堆内存大小设置为服务器物理内存的1/4到1/2之间。可以通过设置启动参数来调整堆内存大小,例如: \-Xmx512m 这个参数将堆内存最大值设置为512MB。 * 调整新生代比例 由于对象的生命周期通常很短,因此大部分对象都存在于新生代中。因此,调整新生代大小和老年代的比例可以影响垃圾回收的效率。通常情况下,推荐将新生代和老年代的比例设置为1:2或者1:3,在这种情况下,新生代将占用总堆内存的1/4到1/5。可以通过设置启动参数来调整新生代比例,例如: \-XX:NewRatio=2 这个参数将新生代和老年代的比例设置为1:2。 * 调整Eden区和Survivor区的大小 当新对象被创建时,它们会被分配到Eden区。如果Eden区没有足够的空间来存放对象,就会触发Minor GC。因此,调整Eden区和Survivor区的大小可以影响Minor GC的效率。通常情况下,推荐将Eden区大小设置为总堆内存的1/8到1/10,同时将Survivor区大小设置为Eden区的1/3。可以通过设置启动参数来调整Eden区和Survivor区的大小,例如: \-XX:MaxNewSize=256m -XX:NewSize=256m -XX:SurvivorRatio=3 这个参数将Eden区大小和Survivor区大小都设置为256MB,并且将Survivor区大小设置为Eden区的1/3。 * 调整垃圾回收器参数 JVM提供了多个垃圾回收器,例如串行GC、并行GC和CMS等。这些垃圾回收器有不同的特点和优缺点,可以根据应用程序的负载和性能需求来选择适当的垃圾回收器。同时,也可以通过调整垃圾回收器的参数来优化垃圾回收效率。例如,可以设置并行GC的线程数: \-XX:ParallelGCThreads=4 这个参数将并行GC的线程数设置为4个。 ![c95d4595fe7643e0b51b1227c6bdb4e1.png][] [367bf1c32faa4c21ae08369d22a58b63.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/17/47cee135bac44b848094a5ef3f0d0ef0.png [a8eef159634a4aae881e4bec3ffe442a.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/17/ae65c79414d04c9cb4707f06b720a768.png [c95d4595fe7643e0b51b1227c6bdb4e1.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/17/2199c2926ee1400f94efdd6272f3d071.png
相关 Java虚拟机内存管理:栈区、堆区、方法区理解 在Java虚拟机(JVM)的内存管理中,主要包括三个区域:栈区、堆区和方法区。下面分别介绍这三个区域: 1. 栈区(Stack): - **局部变量**:每个方法都有自 绝地灬酷狼/ 2024年09月10日 16:42/ 0 赞/ 25 阅读
相关 JVM 如何理解新生区、永久区、堆内存调优? 目录 一、新生区 二、永久区 三、堆内存调优 -------------------- 一、新生区 JVM的堆是Java内存管理的核心,它被用于存储对象和数组。 柔情只为你懂/ 2024年03月17日 10:28/ 0 赞/ 33 阅读
相关 jvm性能调优实战 - 46堆区OOM解析 文章目录 Pre 从对象在Eden区分配开始讲起 高并发场景下导致ygc后存活对象太多 什么时候会发生堆内存的溢出? Case Demo r囧r小猫/ 2023年01月17日 04:48/ 0 赞/ 109 阅读
相关 JVM之永久区Permanent区参数设置分析 引言: JVM中的内存区域一般分为3个部分: 年轻代、年老代和永久代;永久代在JDK 7中逐渐变化,到JDK 8之后完全消失,合并到了Native堆中。本文将逐个分析其中的使用 ゝ一世哀愁。/ 2022年09月24日 15:27/ 0 赞/ 121 阅读
相关 【JVM】内存区 如图,引用自[官网][Link 1] ![这里写图片描述][20160929233203259] 从左到右依次为: “Young”(年轻代): Eden(伊甸园),S ゝ一世哀愁。/ 2022年07月16日 02:55/ 0 赞/ 148 阅读
相关 内存分区-------堆区 栈区 全局数据区 代码区(转) 在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。 栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的 「爱情、让人受尽委屈。」/ 2022年05月24日 05:25/ 0 赞/ 370 阅读
相关 JVM内存区 一、Jdk1.6之前的内存分区大致如下: 1、运行时数据区:线程共享区(堆、方法区【运行时常量池】)- 线程私有区(本地方法栈、Java栈、程序计数器)。 2、非运行时数 客官°小女子只卖身不卖艺/ 2021年11月15日 11:00/ 0 赞/ 281 阅读
相关 JVM 堆、栈、方法区理解(二) 堆、栈、方法区概念和联系 堆解决的是数据存储的问题,即数据怎么放,放在哪儿。 栈解决程序的运行问题,即程序如何执行,或者说如何处理信息。 方法区则是辅助对战的快永久区(P 今天药忘吃喽~/ 2021年09月27日 01:48/ 0 赞/ 328 阅读
相关 JVM--堆内存调优 堆参数 常用参数: -Xms --jvm堆的最小值 -Xmx --jvm堆的最大值 -XX:MaxNewSize --新生代最 「爱情、让人受尽委屈。」/ 2021年08月13日 15:59/ 0 赞/ 417 阅读
还没有评论,来说两句吧...