面试题集中营—GC日志简析及频繁GC的调优

news2024/10/6 5:55:15

如何查看GC日志

        有两种方式查看GC日志,一种是动态命令行查看

        jstat  -gc <pid> 300 5

        第二种就是在JVM参数中增加打印的参数,如下:

       -XX:+PrintGCDetails -XX:+PrintGCTimeStamps   表示打印每次GC的日志以及GC发生的时间

        -Xloggc:gc.log 可以把gc日志写入文件中

JVM配置的堆结构

        -XX:NewSize=5M -XX:MaxNewSize=5M -XX:InitialHeapSize=10M -XX:MaxHeapSize=10M

 -XX:SurvivorRatio=8 -XX:PretenureSizeThreshold=10M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps

        新生代:5M、老年代:5M、Eden区:4M、FromSurvivor和ToSurvivor都是0.5M

GC日志说明

我们来看一个GC日志的打印结果:

0.144: [GC (Allocation Failure) 0.144: [ParNew: 3699K->510K(4608K), 0.0030788 secs] 3699K->1641K(9728K), 0.0031282 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 par new generation   total 4608K, used 3745K [0x00000000ff600000, 0x00000000ffb00000, 0x00000000ffb00000)
  eden space 4096K,  78% used [0x00000000ff600000, 0x00000000ff928980, 0x00000000ffa00000)
  from space 512K,  99% used [0x00000000ffa80000, 0x00000000ffaffb40, 0x00000000ffb00000)
  to   space 512K,   0% used [0x00000000ffa00000, 0x00000000ffa00000, 0x00000000ffa80000)
 concurrent mark-sweep generation total 5120K, used 1130K [0x00000000ffb00000, 0x0000000100000000, 0x0000000100000000)
 Metaspace       used 3151K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 344K, capacity 388K, committed 512K, reserved 1048576K

        第一行是运行时的打印,后面是程序退出时的堆内存结果打印。

        第一行的0.144表示程序运行开始后0.144秒发生了一个GC。这是一次年轻代的GC,年轻代的GC算法是ParNew,3699K->510K表示本次GC清理的空间,4608K表示年轻代的总的可用空间,最后的时间0.0030788s 表示本次GC的时间。后面紧跟着的是年轻代GC前后堆的占用情况,后面9728K是堆内存的总大小。user、sys、real表示用户耗时,系统耗时和实际耗时。

       JVM退出时打印的结果分析:分成了三个部分

       1、年轻代管理,从这里我们能够看出年轻代、Eden区和Survivor区的空间及使用比例。

       2、老年代管理,老年代的GC算法和空间使用情况。

       3、元数据区, 元数据区域及class空间的使用情况。

     JDK1.8默认垃圾处理器

       我们把 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC去掉,来查看一下默认情况下的GC日志。

0.177: [GC (Allocation Failure) [PSYoungGen: 3706K->488K(4608K)] 3706K->1700K(9728K), 0.0068803 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
Heap
 PSYoungGen      total 4608K, used 3711K [0x00000000ffb00000, 0x0000000100000000, 0x0000000100000000)
  eden space 4096K, 78% used [0x00000000ffb00000,0x00000000ffe25c30,0x00000000fff00000)
  from space 512K, 95% used [0x00000000fff00000,0x00000000fff7a020,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 5120K, used 1212K [0x00000000ff600000, 0x00000000ffb00000, 0x00000000ffb00000)
  object space 5120K, 23% used [0x00000000ff600000,0x00000000ff72f020,0x00000000ffb00000)
 Metaspace       used 3154K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 345K, capacity 388K, committed 512K, reserved 1048576K

        上述我们可以看到JDK1.8默认的年轻代垃圾处理器是PSYoungGen,默认的老年代垃圾回收器是ParOldGen。我们后面会单开一章来详细说明一下有关垃圾收集器的概念。

频繁GC调优

       GC分成Minor GC、Major GC 和 Full GC

       Minor GC:从年轻代空间回收内容,也成为Young GC

       Major GC:从老年代空间回收内存

       Full GC:清理整个内容堆 - 既包括年轻代也包括老年代

     Minor GC与Major GC过多

       Minor GC:就是年轻代空间太少不足以分配新的对象,就需要GC。Minor GC过多自然会导致Major GC变多,因为对于无法释放的对象,在多次复制移动后根据复制次数就会转移到老年代。        

      注: Major GC只有CMS这个垃圾回收器才有。

       解决方法:

       1、优化代码逻辑:这里可以参考

       2、如果应用存在大量的短期对象,就适当的增加年轻代的大小;如果应用存在较多的持久对象就适当的增加老年代的大小;

     Full GC

        Full GC(Full Garbage Collection)是对整个堆内存(包括年轻代、老年代、永久代或Metaspace等)进行清理的一种垃圾回收操作。触发Full GC的条件可能包括老年代空间不足、永久代/Metaspace空间不足、显式调用System.gc()等。Full GC的执行会导致相对较长的停顿时间,因为它需要对整个堆内存进行回收。

        CMS垃圾收集器的Full GC日志如下:

38.342: [GC (Allocation Failure) 38.342: [ParNew: 6144K->640K(6144K), 0.0027651 secs] 11491K->8130K(19840K), 0.0028367 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
38.345: [GC (CMS Initial Mark) [1 CMS-initial-mark: 7490K(13696K)] 8146K(19840K), 0.0004821 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
38.345: [CMS-concurrent-mark-start]
38.351: [CMS-concurrent-mark: 0.006/0.006 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
38.351: [CMS-concurrent-preclean-start]
38.351: [CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
38.351: [GC (CMS Final Remark) [YG occupancy: 1073 K (6144 K)]38.351: [Rescan (parallel) , 0.0002674 secs]38.352: [weak refs processing, 0.0000457 secs]38.352: [class unloading, 0.0006265 secs]38.352: [scrub symbol table, 0.0004225 secs]38.353: [scrub string table, 0.0001100 secs][1 CMS-remark: 7490K(13696K)] 8564K(19840K), 0.0015694 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 
38.353: [CMS-concurrent-sweep-start]
38.355: [CMS-concurrent-sweep: 0.002/0.002 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
38.355: [CMS-concurrent-reset-start]
38.355: [CMS-concurrent-reset: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

        解析:FullGC也会包括一次年轻代的GC,我们主要还是从第二行开始看

        第一个阶段(CMS Initial Mark):initial-mark-初始标记节点,后面跟着的7490K是老年代的使用情况,13696K表示整个老年代的大小。8146K表示的是堆内存的使用情况,19840K是整个堆的大小。后面跟着的时间就是初始标记阶段的使用时间。这个阶段主要标记GC ROOTS,这个阶段为STW。

        第二个阶段(CMS-concurrent-mark):并发标记阶段,这个阶段是从第一阶段标记的ROOTS来找存活的对象。和应用程序是并发执行的,并不会停止应用程序。

        第三个阶段(CMS-concurrent-preclean):由于上一个阶段是并发的,那么一些对象的引用会发生变化,如果发生了变化,JVM会标记这个区域为DirtyCard。这个阶段就是重新标记。

        第四个阶段(CMS Final Remark):最终标记阶段,这个阶段会老年代全部的存活对象,包括在并发标记阶段更改或者新创建的引用对象。后面跟着的一些统计数据,比如堆内存的使用情况,扫描花费的时间等。

        第五个阶段(CMS-concurrent-sweep):并发清理阶段,不需要STW,主要是移除不需要的对象释放内存空间。

        第六个阶段(CMS-concurrent-reset):并发重置阶段,主要是为了下一次GC做准备

        Parallel垃圾收集器的Full GC日志如下:

72.884: [GC (Allocation Failure) [PSYoungGen: 6125K->500K(6144K)] 16090K->13017K(19968K), 0.0042736 secs] [Times: user=0.11 sys=0.00, real=0.00 secs] 
72.888: [Full GC (Ergonomics) [PSYoungGen: 500K->0K(6144K)] [ParOldGen: 12517K->12671K(13824K)] 13017K->12671K(19968K), [Metaspace: 5545K->5535K(1056768K)], 0.0794034 secs] [Times: user=0.38 sys=0.00, real=0.08 secs] 
89.479: [Full GC (Ergonomics) [PSYoungGen: 5632K->1599K(6144K)] [ParOldGen: 12671K->13700K(13824K)] 18303K->15299K(19968K), [Metaspace: 5536K->5536K(1056768K)], 0.0526621 secs] [Times: user=0.16 sys=0.00, real=0.05 secs] 
101.378: [Full GC (Ergonomics) [PSYoungGen: 5632K->3391K(6144K)] [ParOldGen: 13700K->13699K(13824K)] 19332K->17090K(19968K), [Metaspace: 5536K->5536K(1056768K)], 0.0493102 secs] [Times: user=0.24 sys=0.00, real=0.05 secs] 

       解析:同样的也是年轻代和老年代同时进行了一次GC。PSYoungGen:使用了Parallel Scavenge并行垃圾收集器的新生代GC前后大小的变化;ParOldGen:使用了Parallel Old并行垃圾收集器的老年代GC前后大小的变化;Metaspace: 元数据区GC前后大小的变化,JDK1.8中引入了元数据区以替代永久代;xxx secs:指GC花费的时间

     触发GC的情况

       1、代码中调用system.gc();

       2、老年代空间不足;

       3、堆中分配了大对象;

      解决方法 

        首先通过分析Full GC的过程,新生代和老年代的占用情况,还有每个阶段的时间。定位到具体的原因,比如我们发现老年代每次Full GC回收的内存很少,或者越来越少,FullGC的频率越来越快,那么就表示在堆中出现了无法释放的对象,每次回收都被标记成存活对象。此时就要配合堆分析工具查看占用内存的对象是哪些,并定位到代码中。

        其次在代码中创建了大对象,在新生代中无法分配就会直接进入老年代,这时也需要优化代码。

        原则上基本不需要怎么进行JVM调优,JVM的本身的设计是低延时高并发大吞吐量的,对于日常的服务来说基本上都可以满足了,只需要调整堆空间的大小即可。

        JVM调优的主要调整的部分:

        1、在内存大小不变的情况下,合理的内容空间分配可以提高系统的吞吐量;

        2、根据业务需要调整垃圾回收器;

        3、重点关注的区域是堆区,里面主要存放对象实例。

JDK工具

        jinfo:查看JVM配置参数信息

        jmap:查看当前程序JVM堆使用情况

        jstat:查看JVM GC统计信息

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1607785.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode:203.移除链表元素

&#x1f3dd;1.问题描述&#xff1a; &#x1f3dd;2.实现代码&#xff1a; typedef struct ListNode ListNode; struct ListNode* removeElements(struct ListNode* head, int val) {if(headNULL)return head;ListNode *NewHead,*NewTail;ListNode *pcurhead;NewHeadNewTail…

电动机保护器在电力系统中的重要性

摘要&#xff1a;在工业自动化领域&#xff0c;低压电动机广泛应用于各种机械设备&#xff0c;例如传动系统、生产线和泵。为了保证这些设备的正常运行&#xff0c;对低压电动机进行必要的保护至关重要。本文将详细介绍低压电动机的七种保护方式&#xff0c;包括过载保护、短路…

spring security登录认证授权

spring security登录认证授权 是什么 Spring Security 主要实现了Authentication&#xff08;认证&#xff0c;解决who are you? &#xff09; 和 Access Control&#xff08;访问控制&#xff0c;也就是what are you allowed to do&#xff1f;&#xff0c;也称为Authorizat…

基于ssm汽车租赁系统业务管理子系统论文

系统简介 随着信息互联网购物的飞速发展&#xff0c;一般企业都去创建属于自己的管理系统。本文介绍了汽车租赁系统业务管理子系统的开发全过程。通过分析企业对于汽车租赁系统业务管理子系统的需求&#xff0c;创建了一个计算机管理汽车租赁系统业务管理子系统的方案。文章介…

【MySQL 数据宝典】【内存结构】- 005 Log Buffer

Log Buffer Log Buffer&#xff1a;日志缓冲区&#xff0c;用来保存要写入磁盘上log文件&#xff08;Redo/Undo&#xff09;的数据&#xff0c;日志缓冲区的内容定期刷新到磁盘log文件中。日志缓冲区满时会自动将其刷新到磁盘&#xff0c;当遇到BLOB或多行更新的大事务操作时&…

【智能排班系统】Quartz结合Cron-Utils自定义时间发送上班、休息提醒

文章目录 Quartz&#xff1a;强大的Java作业调度引擎Quartz概述核心概念与架构配置文件主配置&#xff08;配置主要调度器设置、事务&#xff09;线程池配置&#xff08;调整作业执行资源&#xff09;SimpleThreadPool特定属性自定义线程池 RAMJobStore配置&#xff08;在内存中…

C# 窗体应用程序 Chart控件显示实时曲线

IDE: VS2019 项目模板&#xff1a;C# windows 窗体应用(.NET Framework) 【参考】 B站上教程C#Chart控件画折线图的使用&#xff0c;关于Chart控件的属性&#xff0c;介绍得非常详细。B站上教程C#上位机Chart控件实时曲线终极讲解&#xff0c;对鼠标滚轮事件等&#xff0c;多…

NLP任务全览:涵盖各类NLP自然语言处理任务及其面临的挑战

自然语言处理(Natural Language Processing, 简称NLP&#xff09;是计算机科学与语言学中关注于计算机与人类语言间转换的领域。NLP将非结构化文本数据转换为有意义的见解&#xff0c;促进人与机器之间的无缝通信&#xff0c;使计算机能够理解、解释和生成人类语言。人类等主要…

基于SkyEye运行Qt:著名应用程序开发框架

Qt是一个著名的跨平台的C图形用户界面应用程序开发框架&#xff0c;目前包括Qt Creator、Qt Designer等等快速开发工具&#xff0c;还支持2D/3D图形渲染、OpenGL&#xff0c;允许真正的组件编程&#xff0c;是与GTK、MFC、OWL、ATL一样的图形界面库。使用Qt开发的软件可以做到一…

excel 无法正确处理 1900-03-01 前的日期

问题由来&#xff1a;excel 用公式 TEXT(A1,"yyyy-mm-dd") 转日期时&#xff0c;当A1 的值等于59 的时候&#xff0c;返回值是1900-02-28&#xff1b;当A1 的值等于61 的时候&#xff0c;返回值是1900-03-01&#xff1b;那么当 A1的值为 60 的时候&#xff0c;返回值…

[大模型]MiniCPM-2B-chat WebDemo部署

MiniCPM-2B-chat WebDemo部署 MiniCPM-2B-chat 介绍 MiniCPM 是面壁智能与清华大学自然语言处理实验室共同开源的系列端侧大模型&#xff0c;主体语言模型 MiniCPM-2B 仅有 24亿&#xff08;2.4B&#xff09;的非词嵌入参数量。 经过 SFT 后&#xff0c;MiniCPM 在公开综合性…

开发与产品的战争之自动播放视频

开发与产品的战争之自动播放视频 起因 产品提了个需求&#xff0c;对于网站上的宣传视频&#xff0c;进入页面就自动播放。但是基于我对chromium内核的一些浅薄了解&#xff0c;我当时就给拒绝了: “浏览器不允许”。&#xff08;后续我们浏览器默认都是chromium内核的&#…

C盘越用越大?教你如何科学管理C盘空间

前言&#xff1a; 如图&#xff0c;左边是我多开的E5电脑&#xff0c;装的是LTSC2019_210707F多开封装版&#xff0c;C盘占用8.5GB&#xff0c;右边是我平常打游戏写代码的电脑&#xff0c;装的是Win11 22H2&#xff0c;C盘占用30GB。两台电脑都关闭了休眠&#xff0c;C盘的虚拟…

【鸿蒙开发】画布组件 Canvas

1. Canvas 提供画布组件&#xff0c;用于自定义绘制图形。 接口&#xff1a; Canvas(context?: CanvasRenderingContext2D) 参数&#xff1a; 参数名 参数类型 必填 默认值 参数描述 context CanvasRenderingContext2D 否 - 不支持多个Canvas共用一个CanvasRende…

GPT国内怎么用

2022年11月&#xff0c;OpenAI发布了ChatGPT&#xff0c;这标志着大型语言模型在自然语言处理领域迈出了巨大的一步。ChatGPT不仅在生成文本方面表现出了惊人的流畅度和连贯性&#xff0c;更为人工智能应用开启了全新的可能性。 ChatGPT的推出促进了人工智能技术在多个领域的广…

查看apk是64位32位(三种方法)

通过检查APK文件&#xff0c;你可以确定该APK支持的架构类型&#xff0c;包括它是为64位&#xff08;例如arm64-v8a、x86_64&#xff09;还是32位&#xff08;例如armeabi-v7a、x86&#xff09;架构准备的。Android应用程序可以包含多个不同的二进制文件&#xff0c;每个文件针…

数组和指针的联系(C语言)

数组和指针是两种不同的数据类型&#xff0c;数组是一种构造类型&#xff0c;用于存储一组相同类型的变量&#xff1b;而指针是一种特殊类型&#xff0c;专门用来存放数据的地址。数组名除了sizeof(数组名)和&数组名表示整个数组外&#xff0c;其他情况下都表示的是首元素的…

说说你对图的理解?相关操作有哪些?

一、是什么 在计算机科学中&#xff0c;图是一种抽象的数据类型&#xff0c;在图中的数据元素通常称为结点&#xff0c;V是所有顶点的集合&#xff0c;E是所有边的集合 如果两个顶点v,w&#xff0c;只能由v向w&#xff0c;而不能由w向v&#xff0c;那么我们就把这种情况叫做一…

Leetcode - 周赛393

目录 一&#xff0c;3114. 替换字符可以得到的最晚时间 二&#xff0c;3115. 素数的最大距离 三&#xff0c;3116. 单面值组合的第 K 小金额 四&#xff0c; 3117. 划分数组得到最小的值之和 一&#xff0c;3114. 替换字符可以得到的最晚时间 本题是一道模拟题&#xff0c;…

有效的括号 + 点击消除 || 匹配问题

目录 点击消除&#xff1a; 有效的括号&#xff1a; 点击消除&#xff1a; 点击消除_牛客题霸_牛客网 (nowcoder.com)https://www.nowcoder.com/practice/8d3643ec29654cf8908b5cf3a0479fd5?tpId308&tqId40462&ru/exam/oj 如题目所述&#xff0c; 示例1&#xf…