JVM问题排查和垃圾回收机制

news/2025/3/15 11:04:14/

文章目录

  • JVM问题排查和垃圾回收机制
  • JVM线程共享区
  • 哪些可以作为GC Roots
  • 如何排查JVM问题
  • JVM参数调优
  • JVM与垃圾回收器
  • Java垃圾回收机制
  • 标记-清除与标记-整理算法
    • 标记-清除算法
    • 标记-整理算法

JVM问题排查和垃圾回收机制

JVM线程共享区

JVM内存区主要分为5个区域:

  • 程序计数器:每条线程都有一个程序计数器,它的作用是记住下一条 JVM 要执行的指令的地址。
  • 虚拟机栈:每条线程都有一个私有的虚拟机栈,它的作用是存储局部变量、操作数栈、动态链接、方法出口等信息。
  • 本地方法栈:与虚拟机栈相似,用于Native方法。
  • 方法区:用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
  • 堆:用于存储对象实例,数组等,是垃圾回收器管理的主要区域。

其中,方法区和堆是所有线程共享的,是实现线程通信和协作的关键。

哪些可以作为GC Roots

GC Roots是垃圾回收器的起点,直接或间接地与GC Roots相关的对象就不会被回收。主要的GC Roots有:

  • 本地变量表中引用的对象
  • 虚拟机栈中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI引用的对象

通过以上GC Roots,垃圾回收器可以遍历整个JVM里所有的存活对象,实现垃圾回收。

如何排查JVM问题

当出现JVM问题如内存溢出时,可以通过以下步骤进行排查:

  1. 查看GC日志,分析GC的次数、时间以及回收的内存大小,判断是否是内存泄漏导致的溢出。
  2. 使用JDK自带的JVM监控工具jvisualvm查看内存情况,判断增长最快的区域以及对象。
  3. 使用Arthas等诊断工具,通过oom命令分析内存溢出时的堆栈信息。
  4. 通过btrace或者Arthas追踪某个对象的引用链,判断是否有循环引用导致无法回收。
  5. 使用jmap命令dump出内存镜像,通过MAT、Eclipse Memory Analyzer等工具分析对象关系,找到内存泄漏的对象。
  6. 采样命令如numastat、async-profiler等分析线程状态,判断是否有线程阻塞导致的内存占用过高。
  7. 检查项目的资源释放情况,如数据库连接、文件句柄等,确保及时关闭可以释放的资源。

JVM参数调优

JVM的参数调优是提高JVM性能的重要手段,常见的优化参数有:

  • -Xms和-Xmx:设置JVM堆的初始大小和最大大小,避免每次GC的时候重新分配内存。
  • -XX:NewRatio:设置年轻代和老年代的大小比例,默认为2,可选范围1-n。
  • -XX:SurvivorRatio:设置年轻代中Eden区与Survivor区的大小比例,默认为8,可选范围1-n。
  • -XX:MaxTenuringThreshold:设置对象进入老年代的年龄,可选范围0-15,默认为15。
  • -XX:+UseG1GC:使用G1垃圾回收器,它可以并行、并发地回收年轻代和老年代内存。
  • -XX:ParallelGCThreads:设置垃圾收集器使用的CPU数量,一般设置为CPU核数。
  • -XX:+DisableExplicitGC:关闭System.gc(),避免人为触发GC。
  • -XX:+PrintGCDetails:输出详细的GC日志,用于分析GC情况。

这些参数的设置会根据具体项目的内存情况和需求进行调整,需要结合GC日志和监控工具综合分析,达到以下目标:

  • 减少GC次数:通过加大堆空间和提高对象进入老年代的年龄,尽量减少Minor GC的次数。
  • 平滑GC曲线:避免突发的长时间Full GC,通过并行GC和分代GC实现渐进式GC。
  • 最短GC停顿时间:通过并行GC、G1等新一代GC算法和调整线程数量实现最短GC停顿。
  • 达到60%的内存利用率:通过监控内存使用率,确定Xms和Xmx的设置,避免 overtunning。

JVM与垃圾回收器

JVM的主要内存区有方法区、堆、栈、程序计数器等,堆和方法区是所有线程共享的,其中堆主要用于存储对象实例,是一个显著的可回收内存来源。垃圾回收器的主要工作就是规律的遍历堆区,释放那些不再被使用的对象所占用的内存,使其成为可用内存。

常见的垃圾回收器有:

  • Serial:单线程回收器,会暂停所有的用户线程进行回收,回收完成后才会重新启动用户线程,可能导致较长的GC停顿时间,但简单高效。
  • Parallel:多线程回收器,同时使用多个CPU核心进行垃圾回收以减少停顿时间,在堆内存大于100MB时会自动触发Parallel回收器。
  • CMS:并发标记清除,用户线程与回收线程同时执行,但会产生大量的内存碎片,且当老年代空间用完时会变成Serial回收,会导致较长的停顿时间。
  • G1:G1垃圾回收器将堆内存划分为多个大小相等的Region,并在回收时不需要停顿整个JVM,可以实现最短回收停顿时间和配合指定的内存占用量来达到可控的GC时间。它是Java 9默认的垃圾回收器。

对于系统吞吐量和响应时间都比较高的服务,推荐使用G1或CMS垃圾回收器,通过「-XX:+UseG1GC」或「-XX:+UseConcMarkSweepGC」设置。并且可以设置以下参数:

  • -XX:ParallelGCThreads:设置CMS线程数量,一般与CPU核数相等。
  • -XX:MaxGCPauseMillis:设置GC的最大停顿时间,CMS会尽量不超过这个值,默认是200ms。
  • -XX:InitiatingHeapOccupancyPercent:设置CMS触发的堆内存占用百分比,默认是80%。

联合GC日志分析,tuning的GC参数,选择合适的垃圾回收器是运维一个高性能JAVA应用的关键所在。

如何选择垃圾回收器:

  • 如果应用对吞吐量要求较高,对响应时间较不敏感,可以选择Serial或Parallel回收器。
  • 如果应用是CPU密集型应用,同时对吞吐量和响应时间都有一定要求,可以选择CMS回收器,并适当调高线程数。
  • 如果应用对响应时间比较敏感,而且有较大的堆内存(超过4GB),应选择G1垃圾回收器。
  • 如果应用带有宿主,则必须使用CMS回收器。
  • 如果应用要求实现最短的GC停顿时间并且GC过程可控,应选择G1垃圾回收器,并指定MaxGCPauseMillis时间。

所以,选择合适的垃圾回收器需要综合考虑应用的类型以及对各项性能指标如吞吐量、响应时间、内存占用的需求,并根据具体应用场景选择最优的收集器配置。这也是构建一个高性能Java应用的关键所在。

Java垃圾回收机制

Java垃圾回收主要是利用垃圾回收器对堆内存进行回收,回收那些不再被使用的对象所占用的内存,以实现内存的再利用。

Java垃圾回收机制主要包括:

  • Reachability Roots:这些对象直接或间接地被虚拟机栈或本地方法栈中的引用变量引用,它们是回收的起始点。
  • 可达性分析:从GC Roots开始对堆内存进行搜索,搜索过程遇到的对象被标记为可达对象。
  • 写屏障:写入引用时插入一个屏障,这个屏障会记录此时的引用指向对象的标记状态,并在标记阶段使用。
  • 标记-清除:标记出可达对象,之后清除未标记的对象,这会产生大量内存碎片。
  • 标记-复制:将内存分为两块,每次只用其中一块。标记可达对象后,将存活对象复制到另一块内存,然后清除上一块内存。
  • 标记-整理:标记可达对象后,对未标记对象进行清理,并对存活对象进行整理,使它们在一端连续。

其中,[标记-清除]算法会产生内存碎片较严重,而[标记-复制]算法需要双倍的内存空间,所以目前主流的商业虚拟机一般采用[标记-整理]算法。

虽然我们主要关注标记-清除与标记-整理算法,但其他算法的理解也有助于我们深入理解Java的垃圾回收机制。垃圾回收是Java虚拟机实现自动内存管理的关键,必须理解透彻。

标记-清除与标记-整理算法

标记-清除算法

标记-清除算法主要分为两个阶段:

  1. 标记阶段:从GC Roots开始对堆内存进行可达性分析,标记出所有可达对象。
  2. 清除阶段:清除未标记的对象,释放内存。

该算法的实现过程如下:

  1. GC Roots向下搜索,标记可达对象。
  2. 重复1,直到没有新的可达对象产生。
  3. 清除未标记的对象,实现内存回收。
  4. 可用内存变为未标记对象占用的内存空间。

该算法的主要缺点是会产生大量内存碎片,降低内存利用效率。

标记-整理算法

标记-整理算法通过对象迁移的方式解决了标记-清除算法的内存碎片问题,其实现过程如下:

  1. 标记阶段:与标记-清除算法相同,标记出所有可达对象。
  2. 整理阶段:将所有存活对象向一端移动,然后清除端边界以外的内存。
  3. 设置一个指针,指向未清理的内存起始地址,作为下次分配内存时使用。
  4. 可用内存变为未标记对象占用的内存空间,没有产生内存碎片。

该算法通过对象迁移的方式,实现了内存的整理和压缩,节约了内存空间并消除了内存碎片。其实现过程也相对复杂一些,效率略低于标记-清除算法。

所以,标记-清除算法实现简单但会产生较多内存碎片,标记-整理算法实现相对复杂但可以有效解决内存碎片问题。理解两种算法的实现原理,有助于我们选择和调优合适的垃圾回收器,构建高性能的Java应用。


http://www.ppmy.cn/news/68461.html

相关文章

Oracle监听的优化思路

Oracle监听的优化思路优化思路如下: 为减少客户端和服务端网络之间TCP包的传输数量,可在sqlplus客户端设置参数ARRAYSIZE。假设ARRAYSIZE默认大小为15,表示应用每次将获取15行的数据。如果TCP包大小(排除包头等元数据之后&#x…

也谈零基础学编程,需要学什么

也谈零基础学编程,需要学什么 零基础人群语法1、注释2、变量2.1 变量命名2.2 数据类型2.3 类型强度 3、 运算符4、流程控制与代码块5、函数和方法6、类 算法学会使用第三方库小结 零基础人群 现在开发语言各种各样,越来越多,尤其是 python &…

微服务学习笔记--(Gateway网关)

统一网关Gateway 为什么需要网关gateway快速入门断言工厂过滤器工厂全局过滤器跨域问题 Gateway网关-网关作用介绍 为什么需要网关 网关功能: 身份认证和权限校验服务路由、负载均衡请求限流 网关的技术实现 在SpringCloud中网关的实现包括两种: …

ORACLE 新闻速递 ORACLE 23C 免费提供给开发者 为什么???

开头还是介绍一下群,如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系 liuaustin3 ,在新加的朋友会分到2群(共…

EXCEL: 查找符合多个条件,并且不重复的数据的个数的3种方法:公式,数据透视表,数组公式

1 目标问题:想筛选出(在a列月份为5)且不重复的b列数据有几个 有2个条件 查找第1列月份为5月的并且第2列不重复的数据个数 方法1:用加辅助列简单公式的办法 其实逻辑是更清晰的,就是显得步骤繁琐 第1个辅助列1,查找日期中的月份…

VMware 产品下载汇总 2023 持续更新中

本站 VMware 产品下载汇总:vSphere、NSX、Tanzu、Aria、Cloud… 请访问原文链接:https://sysin.org/blog/vmware/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org 本站提供的 VMware 软件全部为 “试用版…

MySQL 日期函数

MySQL的日期函数主要用来对日期和时间类型的数据进行计算、格式化和转换,能够帮助程序员更加方便地处理存储在MySQL数据库中的时间数据。使用这些函数可以实现以下功能: 格式化日期和时间:通过指定不同的日期格式输出相应的日期或时间字符串…

数据结构lab3-图型结构的建立与搜索

title: 数据结构lab3-图型结构的建立与搜索 date: 2023-05-16 11:42:26 tags: 数据结构与算法 课程名称:数据结构与算法 课程类型:必修 实验项目:图型结构的建立与搜索 实验题目:图的存储结构的建立与搜索 实验日期&#xff1…