垃圾回收机制--GC 垃圾收集器--JVM调优-面试题
1.触发垃圾回收的条件
- 新生代 Eden区域满了,触发young gc (ygc)
- 老年代区域满了,触发full gc (fgc)
- 通过ygc后进入老年代的平均大小大于老年代的可用内存,触发full gc(fgc).
- 程序中主动调用的System.gc()强制执行gc,是full gc,但是不必然执行。
2.垃圾回收流程
- 当Eden满后,会触发young gc, 把有引用存活的对象复制到S0区域,回收清空Eden区域。
- 当Eden再次满后,触发young gc, 把Eden和S0区域的存活对象复制到另一个S1区域,收回清空Eden和S0区域。
2.GC问题排查流程
GC问题的排查流程主要包括观察GC日志、分析内存使用情况、寻找GC导致的性能问题、调整GC参数、使用垃圾收集器分析工具和进行压力测试和性能调优。根据具体情况,可能需要结合多种方法和工具来诊断和解决GC问题。
也可以通过 使用jmap命令查某时刻的JVM堆信息,查看占用比较高的对象
3.对象进入老年代的场景
对象首次创建会被放置在新生代的eden区
对象进入老年代主要有下面三种方式:
- 大对象
-
- 比如很长的字符串、很大的数组等
- 可通过参数-XX:PretenureSizeThreshold=3145728设置,超过这个参数设置的值就直接进入老年代
- 长期存活的对象
-
- 对象头中(Header)包含了 GC 分代年 龄标记信息。如果对象在 eden 区出生,那么它的 GC 分代年龄会初始值为 1
- 每熬过一次 Minor GC 而不被回收,这个值就会增 加 1 岁。当它的年龄到达一定的数值时,就会晋升到老年代中
- 可以通过参数 -XX:MaxTenuringThreshold 设置年龄阀值(默认是 15 岁)
- 动态对象年龄判定
-
- 当 Survivor 空间中相同年龄所有对象的大小总和大于 Survivor 空间的一半。
- 年龄大于或等于该年龄的对象就可以直接进入老年代,而不需要达到默认的分代年龄。
4.GC年龄代为什么默认是15,可以自定义吗? 最大最小可以设置多少
这个默认值是根据实践经验和性能测试得出的,可以尽可能的的保证垃圾回收效率的前提下减少移动到老年代的对象数量;从而减少Full gc
最小是1,不可以设置为负数或0
最大值是15,原因是对象的GC年龄存储在对象头里,分配4bit存储,转换为二进制就是15.
5.对象存活判定
由于程序计数器、栈、本地方法栈都是线程独享,其占用的内存是随线程结束而回收。而Java堆和方法区则不同,线程共享,是GC的所关注的部分。
引用计数算法
给对象添加一个引用计数器,当有一个地方引用对象是计数器加1,当引用失效是计数器减1,当该对象的计数器为0时表示可以回收。
可达性分析算法
从GC Roots对象作为起点向下搜索,当一个对象不在GC Roots的引用链路中时,该对象可以回收。
GC Roots对象包含:方法区静态属性引用的对象、栈中引用的对象、本地方法栈中Native方法引用的对象、常量引用的对象。
从GC Roots开始,把所有可以搜索得到的对象标记为存活对象,固定可作为GC Roots的对象包括以下几种:·
v 在虚拟机栈(栈帧中的本地变量表)中引用的对象,譬如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等。·
v 在方法区中类静态属性引用的对象,譬如Java类的引用类型静态变量。·在方法区中常量引用的对象,譬如字符串常量池(String Table)里的引用。
v 在本地方法栈中Native方法引用的对象。
v Java虚拟机内部的引用,如基本数据类型对应的Class对象,一些常驻的异常对象(比如NullPointExcepiton、OutOfMemoryError)等,还有系统类加载器。
v 所有被同步锁(synchronized关键字)持有的对象。
GC 垃圾收集器
1.你知道哪些垃圾收集器?
新生代收集器:
- 串行-收集器 Serial (单线程、复制算法) [-XX:+UseSerialGC]
- Parallel Scavenge 收集器(多线程,复制算法)
- ParNew (Serial+多线程 , 复制算法)[-XX:+UseParNewGC]
-
- ParallelScavenge [-XX:+UseParallelGC]
- G1 (多线程标记清除算法)
老年代收集器:
- SerialOld(单线程、标记整理算法) [ -XX:+UseSerialOldGC ]
- ParallelOld(多线程标记整理算法) [ -XX:+UseParallelOldGC]
- CMS(-XX:+UseConcMarkSweepGC)(多线程标记清除法)
- G1(多线程标记整理算法) [-XX:+UseG1GC]
G1是一个独立的收集器不依。ZGC是目前JDK 11的实验收集器。
2.你们项目中用的哪些
- 老年代用的 cms
- 新生代用的 ParNew (使用复制算法完成垃圾收集)
3.CMS
3.1 CMS的流程
- 初始化标记,短暂的暂停工作线程,标记出可达对象;
- 并发标记,和用户线程并发执行,跟踪对象;
- 重新标记,暂停用户线程,重新标记因程序运行而不可达的点;
- 并发清除,和用户线程并发执行,清除不可达对象。
- 初始标记(STW initial mark):
-
- 从垃圾回收的"根对象"开始,只扫描到能够和"根对象"直接关联的对象,并作标记。所以这个过程虽然暂停了整个JVM,但是很快就完成了。(标记GC Roots存活对象)短暂stop the word
- 并发标记(Concurrent marking):和用户线程一起并发执行,跟踪对象(对GC Roots对象引用进行追踪,标记存活)
-
- 并发预清理(Concurrent precleaning):并发预清理阶段仍然是并发的。在这个阶段,虚拟机查找在执行并发标记阶段新进入老年代的对象(可能会有一些对象从新生代晋升到老年代, 或者有一些对象被分配到老年代)。通过重新扫描,减少下一个阶段"重新标记"的工作,因为下一个阶段会Stop The World。
- 重新标记(STW remark):短暂暂停,扫描在“并发标记”过程中被标记为可达或新创建的对象,
- 并发清理(Concurrent sweeping):清理垃圾对象,这个阶段收集器线程和应用程序线程并发执行。
- 并发重置(Concurrent reset):这个阶段,重置CMS收集器的数据结构状态,等待下一次垃圾回收。
低停顿的老年代垃圾回收器,通过初始标记,并发标记两个阶段来实现垃圾回收,。
3.2 CMS的缺点
CMS都有哪些问题?
- 内存碎片问题。Full GC的整理阶段,会造成较长时间的停顿。
- 需要预留空间,用来分配收集阶段产生的“浮动垃圾”。
- 由于并发标记和并发清理阶段都是并发执行,所以会额外消耗CPU资源
- 停顿时间是不可预期的。
解决老年代碎片化问题的办法
CMS在进行一定次数的Full GC(标记清除)的时候进行一次标记整理算法,
-XX:UseCMSCompactAtFullCollection -XX:CMSFullGCBeforeCompaction=5
4.G1收集器
4.1 简介
G1是JDK8 开始有在JDK9作为默认垃圾回收器。
- 在多处理器和大容量内存环境中。能充分利用资源,尽量缩短STW。
- 采用标记-整理算法不会产生内存碎片(局部是通过复制算法)
- 把内存划分为多个独立分区Region
- 可预测的停顿时间模型
-
- 可以自己通过参数-XX:MaxGCPauseMillis来设置允许的停顿时间(默认200ms),
- 为每个Region记录回收的空间大小、所需时间,维护一个优先级列表,基于设置的停顿时间优先回收。
其他:
JVM最多可以有2048个Region。一般Region大小等于堆大小除以2048,比如堆大小为4096M,则Region大小为2M。
- G1 垃圾收集器对于对象什么时候会转移到老年代跟之前讲过的原则一样,唯一不同的是对大对象的处理,G1有专门分配大对象的Humongous区,对G1来说,超过一个Region一半大小的对象都被认为大对象,将会被放入Humongous Region,而对于超过整个Region的大对象,则用几个连续的Humongous来存储。
- Full GC 的时候除了收集年轻代和老年代之外,也会将Humongous区一并回收。
4.2 G1回收过程
- 初始标记(initial mark,STW):暂停所有的线程,并记录下gc roots直接能引用的对象,速度很快;
- 并发标记(Concurrent Marking):和用户线程并发执行,跟踪对象;
- 最终标记(Remark,STW):短暂暂停用户线程,重新标记因程序运行而不可达的点;
- 筛选回收(Cleanup,STW):更新Region的统计数据,对每个Region的回收价值和成本排序,根据用户设置的停顿时间制定回收计划。再把需要回收的Region中存活对象复制到空的Region,同时清理旧的Region。
4.3 实现可预测停顿的方式:
G1收集器通过使用多线程和并发标记清除阶段来实现可预测停顿。
- 可预测的停顿时间模型
-
- 可以自己通过参数-XX:MaxGCPauseMillis来设置允许的停顿时间(默认200ms),
- 为每个Region记录回收的空间大小、所需时间,维护一个优先级列表,基于设置的停顿时间优先回收。
44.Region的大小和结构:
G1将堆划分为多个大小相等的Region,每个Region的大小可以是1MB到32MB之间。Region的大小由用户在启动JVM时通过参数进行配置。
G1的堆结构由多个类型的Region组成,包括:
- Eden Region:新对象被分配到的初始区域。
- Survivor Region:用于存储幸存的对象,用于年轻代的垃圾回收。
- Old Region:用于存储长期存活的对象和被晋升的对象。
- Humongous Region:用于存储大对象,超过了一个Region大小的对象。
G1收集器使用了多个Region之间的引用关系和各个Region之间的协作,来实现高效的并发标记和回收,以及垃圾回收的可预测性。
4.5 G1适合场景
- 50%以上的堆被存活对象占用
- 对象分配和晋升的速度变化非常大
- 垃圾回收时间特别长,超过1秒
- 8GB以上的堆内存(建议值)
- 停顿时间是500ms以内
5.G1与CMS的区别
- 使用范围不一样
-
- CMS是老年代的收集器,可以配合新生代的Serial和ParNew收集器一起使用
- G1收集范围是老年代和新生代。不需要结合其他收集器使用
- 回收垃圾的时间( stop the world )
-
- CMS以最小的停顿时间为目标的收集器。
- G1可预测垃圾回收的停顿时间(建立可预测的停顿时间模型)
- 垃圾碎片
-
- CMS使用“标记-清除”算法进行的垃圾回收,容易产生内存碎片
- G1使用的是“标记-整理”算法,进行了空间整合,降低了内存空间碎片。
- 垃圾回收的过程不一样
-
- CMS: 初始标记、并发标记、并发预清理、重新标记、并发清理、并发重置
- G1 : 初始标记、并发标记、最终标记、筛选回收
- 在大对象的处理上
-
- CMS中若一个大对象,进入S1、S2区域的时候大于改分配的区域,对象会直接进入老年代
- G1处理大对象时会判断对象是否大于一个Region大小的50%,如果大于50%就会横跨多个Region进行存放
6.G1与ZGC
- ZGC: JDK11 中推出的一款低延迟垃圾回收器,适用于大内存低延迟服务的内存管理和回收,SPECjbb 2015 基准测试,在 128G 的大堆下,最大停顿时间才 1.68 ms,停顿时间远胜于 G1 和 CMS。
- 与G1一样,ZGC也采用基于Region的堆内存布局,不一样的是ZGC的Region具有动态性:动态创建销毁、动态容量大小
7.G1 提供的JVM参数配置
G1(Garbage-First)垃圾回收器提供了一些JVM参数配置,用于调整G1垃圾回收器的行为和性能。以下是一些常用的G1相关的JVM参数配置:
-XX:+UseG1GC
:启用G1垃圾回收器。-XX:MaxGCPauseMillis=<n>
:设置期望的最大垃圾回收停顿时间(毫秒)。G1会尽量控制垃圾回收停顿时间不超过该值。-XX:G1HeapRegionSize=<n>
:设置G1堆区的区域大小。默认值为堆大小的1/2000,一般不需要手动设置。-XX:ParallelGCThreads=<n>
:设置并行垃圾回收的线程数。-XX:ConcGCThreads=<n>
:设置并发标记阶段的线程数。-XX:InitiatingHeapOccupancyPercent=<n>
:设置触发混合收集的堆占用百分比阈值。当堆占用达到该阈值时,G1会触发混合收集。-XX:G1ReservePercent=<n>
:设置G1堆区的保留空间百分比。默认值为10,表示G1会保留10%的堆空间不被回收。-XX:G1HeapWastePercent=<n>
:设置G1堆区的废弃空间百分比阈值。当堆区的废弃空间超过该阈值时,G1会执行回收操作。-XX:G1MixedGCLiveThresholdPercent=<n>
:设置混合收集过程中存活对象的阈值百分比。默认值为65,表示混合收集过程中如果存活对象超过65%,则会触发Full GC。
这些参数可以根据具体的应用场景和性能需求进行调整。注意,在使用G1垃圾回收器时,不需要手动设置很多参数,因为G1会根据堆的大小和系统配置自动调整一些参数。建议在需要微调性能时再考虑调整这些参数。
附录:详细介绍
1.Serial (单线程、复制算法)[ -XX:+UseSerialGC ]
- 用于新生代
- 单线程、最基本的垃圾回收器,使用复制算法
- 只使用一个CPU或一个线程去完成垃圾收集工作,并且在进行垃圾收集的同时,需暂停其他所有的工作线程,直到垃圾收集结束。
- 配置参数:
收集过程
- 使用复制算法进行回收
- 将eden和from survivor 区活跃的对象复制到to survivor区,并清空eden区和from survivor区,
- 如果to survivor区满了,那么部分对象将会被晋升移动到老年代,随后交换from和to区。
优缺点:
- 单线程地好处就是减少上下文切换,减少系统资源的开销。
- 但在GC的过程中,会暂停程序的执行。若GC不是频繁发生,这或许是一个不错的选择,否则将会影响程序的执行性能。 对于新生代来说,区域比较小,停顿时间短,所以比较使用。
2.Serial Old(单线程、标记整理算法 )
- Serial 垃圾收集器,用于年老代的版本。
- 单线程、最基本的垃圾回收器,使用标记-压缩-清理算法
在回收阶段,将标记对象越过堆的空闲区移动到堆的另一端,所有被移动的对象的引用也会被更新指向新的位置。
3.ParNew (Serial+多线程 , 复制算法 )[ -XX:+UseParNewGC ]
- ParNew收集器是Serial收集器的多线程版本
- 使用复制算法完成垃圾收集
- 默认开启的收集线程数与CPU的数量相同,可使用 XX:ParallelGCThreads 参数来限制垃圾收集的线程数
- 并行仅仅指的是收集多线程并行, ParNew 垃圾收集器在垃圾收集过程中同样也要短暂暂停所有其他的工作线程。
- 可与CMS收集器配合工作。
4.Parallel (多线程复制算法、高效 ) [ -XX:+UseParallelGC ]
- 通过多线程完成垃圾的清理工作
- 使用复制算法完成垃圾收集
- 占用较低的CPU因而能提高应用的吞吐
5.ParallelOld (多线程标记整理算法)[ -XX:+UseParallelOldGC ]
- 多个线程来完成
- 使用算标记 - 整理算法
- JDK1.6之后才开始提供,是一个老年代收集器
- 能保证新生代的吞吐量优先,无法保证整体的吞吐量
通过目标参数-XX:MaxGCPauseMills和-XX:GCTimeRatio,调整新生代空间大小,来降低GC触发的频率。
并行收集器适合对吞吐量要求远远高于延迟要求的场景,并且在满足最差延时的情况下,并行收集器将提供最佳的吞吐量。
如果系统对吞吐量要求比较高,可以优先考虑新生代 Parallel Scavenge
和年老代 Parallel Old 收集器的搭配策略。
6.CMS(多线程标记清除算法)
- 针对老年代的多线程收集器
- 实现了让垃圾收集器与用户线程(近似)同时工作
CMS(Concurrent Mark Sweep)收集器具有以下特点:
- 基于"标记-清除"算法;
- 以获取最短回收停顿时间为目标;
- 并发收集,停顿时间短。
CMS执行过程:
- 初始标记(STW initial mark):
-
- 从垃圾回收的"根对象"开始,只扫描到能够和"根对象"直接关联的对象,并作标记。所以这个过程虽然暂停了整个JVM,但是很快就完成了。(标记GC Roots存活对象)
- 并发标记(Concurrent marking):这个阶段紧随初始标记阶段,在初始标记的基础上继续向下追溯标记。并发标记阶段,应用程序的线程和并发标记的线程并发执行,所以用户不会感受到停顿。(对GC Roots对象引用进行追踪,标记存活)
- 并发预清理(Concurrent precleaning):并发预清理阶段仍然是并发的。在这个阶段,虚拟机查找在执行并发标记阶段新进入老年代的对象(可能会有一些对象从新生代晋升到老年代, 或者有一些对象被分配到老年代)。通过重新扫描,减少下一个阶段"重新标记"的工作,因为下一个阶段会Stop The World。
- 重新标记(STW remark):这个阶段会暂停虚拟机,收集器线程扫描在CMS堆中剩余的对象。扫描从"跟对象"开始向下追溯,并处理对象关联。
- 并发清理(Concurrent sweeping):清理垃圾对象,这个阶段收集器线程和应用程序线程并发执行。
- 并发重置(Concurrent reset):这个阶段,重置CMS收集器的数据结构状态,等待下一次垃圾回收。
内存碎片问题:
-XX:UseCMSCoimpactAtFullCollection 默认打开,在cms fgc后会STW进行碎片整理。
-XX:CMSFullGCsBeforeCompaction=0 默认0,多少次fgc后进行一次碎片整理,0每次fgc后都整理。
concurrent mode failure 问题:
CMS并发处理中,年轻代移到到老年代内存不够,老年代的垃圾收集器从CMS退化为Serial Old,所有应用线程被暂停。
-XX:CMSInitiatingOccupancyFraction=N调小,并启用碎片整理
CMS 也有一些缺点,其中最大的问题就是老年代内存碎片问题(因为不压缩),
在某些情况下 GC 会造成不可预测的暂停时间,特别是堆内存较大的情况下。
7.G1 收集器
G1收集器概述
JDK1.7后全新的JVM垃圾收集器G1收集器, 目标用于取代CMS收集器。
- G1收集器的最大特点
- G1最大的特点是引入分区的思路,弱化了分代的概念。
- 合理利用垃圾收集各个周期的资源,解决了其他收集器甚至CMS的众多缺陷。
2. G1相比较CMS的改进
- 算法: G1基于标记-整理算法, 不会产生空间碎片,分配大对象时不会无法得到连续的空间而提前触发一次FULL GC。
- 停顿时间可控: G1可以通过设置预期停顿时间(Pause Time)来控制垃圾收集时间避免应用雪崩现象。
- 并行与并发:G1能更充分的利用CPU,多核环境下的硬件优势来缩短stop the world的停顿时间。
3. CMS和G1的区别
- CMS中,堆被分为PermGen,YoungGen,OldGen;而YoungGen又分了两个survivo区域。在G1中,堆被平均分成几个区域(region),在每个区域中,虽然也保留了新老代的概念,但是收集器是以整个区域为单位收集的。
- G1在回收内存后会马上同时做合并空闲内存的工作、而CMS默认是在STW(stop the world)的时候做。
- G1会在Young GC中使用、而CMS只能在O区使用。
4. G1收集器的应用场景
G1垃圾收集算法主要应用在多CPU大内存的服务中,在满足高吞吐量的同时,尽可能的满足垃圾回收时的暂停时间。
就目前而言、CMS还是默认首选的GC策略、可能在以下场景下G1更适合:
- 服务端多核CPU、JVM内存占用较大的应用(至少大于4G)
- 应用在运行过程中会产生大量内存碎片、需要经常压缩空间
- 想要更可控、可预期的GC停顿周期,防止高并发下应用雪崩现象
Garbage first 垃圾收集器是目前垃圾收集器理论发展的最前沿成果,相比与 CMS 收集器,G1 收
集器两个最突出的改进是:
- 基于标记-整理算法,不产生内存碎片。
- 可以非常精确控制停顿时间,在不牺牲吞吐量前提下,实现低停顿垃圾回收。
G1 收集器避免全区域垃圾收集,它把堆内存划分为大小固定的几个独立区域,并且跟踪这些区域
的垃圾收集进度,同时在后台维护一个优先级列表,每次根据所允许的收集时间,优先回收垃圾
最多的区域。区域划分和优先级区域回收机制,确保 G1 收集器可以在有限时间获得最高的垃圾收
集效率。
JVM调优
1.什么时候需要JVM调优
- 应用的响应慢、CPU占用高
- 应用吞吐量小,占用内存空间过大
这些表象一般伴随着频繁的垃圾回收,或者OOM。
2.JVM调优一般调什么
- 内存调优(堆内存,元空间内存)
- 堆栈大小,避免栈溢出错误
- GC调优
-
- 新生代老年代的大小,比例
- 垃圾回收器的选择
- 内存对象优化
-
- 避免内存泄漏,及时释放不再使用的对象引用,避免频繁创建和销毁对象,减少垃圾回收的压力。
堆内存参数
-Xms512m | 初始堆大小 默认值:若未设置,初始值将是老年代和年轻代分配制内存之和 |
-Xmx1024m | 堆内存最大值。 |
年轻代内存相关参数
-Xmn512m | 新生代的初始值及最大值。 默认值:堆内存的1/4(已经分配的堆内存的1/4)。 |
-XX:NewSize=512m | 设置新生代的初始值。 |
-XX:MaxNewSize=512m | 设置新生代的最大值。 |
-XX:NewRatio=8 | 老年代和年轻代的比例。 比如:-XX:NewRatio=8 表示:老年代内存:年轻代内存=8:1 |
-XX:SurvivorRatio=8 | 新生代和存活区的比例 -XX:SurvivorRatio=8 表示存活区:新生代=1:8 =》新生代占年轻代的8/10,每个存活区各占年轻代的1/10 |
元空间参数
-XX:MetaspaceSize | 初始元空间大小 达到该值就会触发垃圾收集进行类型卸载 |
-XX:MaxMetaspaceSize=256m | 设置元空间的最大值,默认是没有上限的,也就是说你的系统内存上限是多少它就是多少。 |
3.JVM调优回答
一般 应用的响应慢、CPU占用高,gc次数高,发生了OOM,排除是代码问题后,是需要调优了。
1.如果是原生内存不足,可以通过 jmap -heap pid 查看 jvm 内存分配
1.定位需要调优的位置(首先定位内存占用在那里,是否是内存泄漏)
- 有GC日志,可通过GC日志查看内存回收情况。
- 有内存快照可通过工具例如Mat,JVisualVM 导入快照查看内存占用高的对象。
- 没有内存快照,可通过jmap手动生成内存快照。
2.定位到问题后针对问题调整参数
比如:堆的大小,新生代,老生代的比例,减少fulklgc
3.JVM调优基本步骤
首先在启动程序的时候
3.1添加GC日志相关的参数
-XX:+PrintGC:输出GC日志
-XX:+PrintGCDetails:输出GC的详细日志
-XX:+PrintGCTimeStamps:输出GC的时间戳(以基准时间的形式)
-XX:+PrintGCDateStamps:输出GC的时间戳(以日期的形式,如2018-08-29T19:22:48.741-0800)
-XX:+PrintHeapAtGC:在进行GC的前后打印出堆的信息
-Xloggc:gc.log:日志文件的输出路径
3.2添加内存溢出与Full gc前快照输出参数
-XX:+HeapDumpOnOutOfMemoryError 发生内存溢出时生成heapdump文件
-XX:+HeapDumpBeforeFullGC 发生Full gc前生成heapdump文件
-XX:HeapDumpPath:指定heapdump输出路径
3.3通过日志确定问题
3.3.1堆内存不足
- 排查是否是设置的堆内存过小,还是内存溢出情况。
- 拿到当时的内存快照,用工具分析 jump用Mat工具分析。
3.3.2频繁Full gc
- 考虑是否是新上线的代码问题,有大对象占用,导致了频繁YGC,进而导致了晋升至年老代的对象增多,老年代达到内存阈值触发 Full gc ;
- 考虑是否是新生代设置太小 ;
总结:
若是代码问题可通过版本控制工具找到本期变更的代码,优化代码
若非代码问题,可适当增加堆内存大小、新生代老年代的大小与比例 , 适当增大新生代内存大小。
4.监控工具
4.1使用jstat 统计gc相关信息
jstat 是 jdk bin 下自带工具,最多的是用来统计gc相关信息,使用步骤如下。
- 获取进程号 ps -ef|grep 对应进程
- 例如我想统计
jvm-demo.jar
(进程号27164)的gc信息,并且每隔3秒统计一次,可以执行以下命令
jstat -gcutil 27164 3000
主要关注以下几个。
- s0、s1:表示两个survior区域的使用百分比
- e:eden区域使用百分比
- o:老年代使用百分比
- m:metaspace(元数据空间)使用百分比
- ygc:新生代gc次数
- ygct:新生代gc累计总时间
- fgc:full gc次数
- fgct:full gc累计总时间
- gct:gc累计总时间
若要进一步查看上一次GC信息
jstat -gccause 27146 3000
- LGCC:上一次gc的原因,Allocation Failure是新生代满了,进行gc
- gcc:当前gc的原因,如果当前没有gc就no gc
4.2使用jmap命令查某时刻的JVM堆信息
使用步骤
- 获取进行 pid ps -ef|grep 对应进程
- 例如我想统计
jvm-demo.jar
(进程号27164)的信息,并且每隔3秒统计一次,可以执行以下命令
jmap -heap 2865
输出内容示例:
Attaching to process ID 27146, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.144-b01using thread-local object allocation.
Mark Sweep Compact GC#堆相关的配置信息
Heap Configuration:MinHeapFreeRatio = 40MaxHeapFreeRatio = 70MaxHeapSize = 104857600 (100.0MB)NewSize = 10485760 (10.0MB)MaxNewSize = 34930688 (33.3125MB)OldSize = 20971520 (20.0MB)NewRatio = 2SurvivorRatio = 8MetaspaceSize = 21807104 (20.796875MB)CompressedClassSpaceSize = 1073741824 (1024.0MB)MaxMetaspaceSize = 17592186044415 MBG1HeapRegionSize = 0 (0.0MB)#堆占用相关的配置信息
Heap Usage:
New Generation (Eden + 1 Survivor Space):capacity = 12517376 (11.9375MB)used = 10708296 (10.212226867675781MB)free = 1809080 (1.7252731323242188MB)85.54745020042539% used
Eden Space:capacity = 11141120 (10.625MB)used = 10708272 (10.212203979492188MB)free = 432848 (0.4127960205078125MB)96.11486098345588% used
From Space:capacity = 1376256 (1.3125MB)used = 24 (2.288818359375E-5MB)free = 1376232 (1.3124771118164062MB)0.0017438616071428572% used
To Space:capacity = 1376256 (1.3125MB)used = 0 (0.0MB)free = 1376256 (1.3125MB)0.0% used
tenured generation:capacity = 27684864 (26.40234375MB)used = 27096504 (25.84123992919922MB)free = 588360 (0.5611038208007812MB)97.87479541167332% used15431 interned Strings occupying 2044328 bytes.
5.常用的调优工具有哪些?
JDK内置的命令行:jps(查看jvm进程信息)、jstat(监视jvm运行状态的,比如gc情况、jvm内存情况、类加载情况等)、jinfo(查看jvm参数的,也可动态调整)、jmap(生成dump文件的,在dump的时候会影响线上服务)、jhat(分析dump的,但是一般都将dump导出放到mat上分析)、jstack(查看线程的)。
JDK内置的可视化界面:JConsole、JVisualVM,这两个在QA环境压测的时候很有用。
阿里巴巴开源的arthas:神器,线上调优很方便,安装和显示效果都很友好
可以查看层级关系的工具
ibm的was服务器产生的dump文件,要用他特有的jar包才可以看。
使用ha456.jar 查看dump文件。
java –Xmx5g -jar ha456.jar
链接:百度网盘 请输入提取码 密码:5vp4
6.手动打Dump
jmap -dump:format=b,file=文件名 [pid]^C
常见参数配置
类加载设置
-XX:+TraceClassLoading:类加载日志
-XX:+TraceClassUnloading:类卸载日志
堆设置
-Xms:初始堆大小
-Xmx:最大堆大小
-XX:NewSize=n:设置年轻代大小
-XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
-XX:MaxPermSize=n:设置持久代大小
收集器设置
-XX:+UseSerialGC:设置串行收集器
-XX:+UseParallelGC:设置并行收集器
-XX:+UseParalledlOldGC:设置并行年老代收集
-XX:+UseConcMarkSweepGC:设置并发收集器
垃圾回收统计信息
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename
并行收集器设置
-XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数。
-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
并发收集器设置
-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况
-XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。
分类 | 参数 | 说明 |
标准参数 | -server | jvm使用server模式,默认该模式,特点启动慢、运行性能和内存管理效率很高,适用生产环境。 |
-client | jvm使用client模式,特点启动快、运行性能和内存管理效率不高,适用开发调试。 | |
-Dproperty=value | 设置系统属性,可用System.getProperty(“property”)获取,如果value中有空格,则需要用双引号将该值括起来,如-Dname=”space string”,该参数通常用于设置系统级全局变量值 | |
-verbose:gc | 表示输出虚拟机中GC的详细情况 | |
堆内存 | -Xms2g | jvm内存(堆内存)启动初始值 默认是物理内存的1/64 |
-Xmx3g | jvm内存(堆内存)最大值 默认是物理内存的1/4 | |
-Xmn1g | 年轻代大小 | |
栈内存 | -Xss1m | 每个线程java虚拟机栈大小 |
-Xoss128k | 本地方法栈大小 HotSpot不区分虚拟机栈和本地方法栈,该参数无效 | |
内存分配 | -XX:PermSize=48m | 设置永久代初始大小 默认20.75M |
-XX:MaxPermSize=128m | 设置永久代最大可分配空间 32位机器默认64M 64位机器默认82M | |
-XX:NewRatio=4 | 表示设置年轻代(包括Eden和两个Survivor区)/老年代 的大小比值为1:4,这意味着年轻代占整个堆的1/5 | |
-XX:SurvivorRatio=8 | 表示设置2个Survivor区:1个Eden区的大小比值为2:8,这意味着Survivor区占整个年轻代的1/5,这个参数默认为8 | |
进入老年代 | -XX:PretenureSizeThreshold=3145728 | 表示对象大于3145728(3M)时直接进入老年代分配,这里只能以字节作为单位 |
-XX:MaxTenuringThreshold=1 | 表示对象年龄大于1,自动进入老年代,如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象在年轻代的存活时间,增加在年轻代被回收的概率。最大15 | |
-XX:TargetSurvivorRatio | 默认50,动态年龄判断 年龄1、2...n累计到达S区50%,年龄n及以上进入老年代 | |
参数配置 | -Xloggc:filePath | 配置gc日志路径 |
-XX:+PrintGCDetails | 打印详细的gc日志 | |
-XX:+PrintGCTimeStamps | 打印gc发生的时间 | |
-XX:+TraceClassLoading | 表示查看类的加载信息 | |
-XX:+TraceClassUnLoading | 表示查看类的卸载信息 | |
-XX:+HeapDumpOnOutOfMemoryError | 表示可以让虚拟机在出现内存溢出异常时Dump出当前的堆内存转储快照 | |
-XX:HeapDumpPath | 内存溢出异常时Dump出堆内存快照路径 | |
-XX:CompileThreshold=1000 | 表示一个方法被调用1000次之后,会被认为是热点代码,并触发即时编译 | |
-XX:+PrintHeapAtGC | 表示可以看到每次GC前后堆内存布局 | |
-XX:+PrintTLAB | 表示可以看到TLAB的使用情况 | |
-XX:+UseSpining | 开启自旋锁 | |
-XX:PreBlockSpin | 更改自旋锁的自旋次数,使用这个参数必须先开启自旋锁 | |
-XX:DisableExplicitGC | 禁止显示执行GC,即禁止代码触发GC(System.gc();) | |
调优参数 | -XX:+ExplicitGCInvokesConcurrent | 命令JVM无论什么时候调用系统GC,都执行CMS GC,而不是Full GC。 |
-XX:+ParallelRefProcEnabled | 并行处理Reference,加快处理速度,缩短耗时 | |
-XX:UseCMSCompactAtFullCollection | full gc压缩 默认true开启 | |
-XX:CMSFullGCsBeforeCompaction | 多少次full gc做压缩,默认0,每次full gc后压缩碎片 | |
-XX:CMSInitiatingOccupancyFraction=92 | 是指设定CMS在对内存占用率达到92%的时候开始GC(因为CMS会有浮动垃圾,所以一般都较早启动GC) | |
-XX:+UseCMSInitiatingOccupancyOnly | 只是用设定的回收阈值(上面指定的92%),如果不指定,JVM仅在第一次使用设定值,后续则自动调整. | |
-XX:+CMSScavengeBeforeRemark | 在CMS GC重新标记前启动一次ygc,目的在于减少old gen对ygc gen的引用,降低remark时的开销(一般CMS的GC耗时 80%都在remark阶段) | |
-XX:+CMSParallelInitialMarkEnabled | 在CMS垃圾回收器的“初始标记”阶段开启多线程并发执行 | |
垃圾回收器 | -XX:+UseG1GC | 表示让JVM使用G1垃圾收集器 |
-XX:+UseSerialGC | 表示使用jvm的串行垃圾回收机制,该机制适用于单核cpu的环境下 | |
-XX:+UseParallelGC | 表示使用jvm的并行垃圾回收机制,该机制适合用于多cpu机制,同时对响应时间无强硬要求的环境下,使用-XX:ParallelGCThreads=设置并行垃圾回收的线程数,此值可以设置与机器处理器数量相等。 | |
-XX:+UseParallelOldGC | 表示年老代使用并行的垃圾回收机制 | |
-XX:+UseConcMarkSweepGC | 表示使用并发模式的垃圾回收机制,该模式适用于对响应时间要求高,具有多cpu的环境下 | |
G1参数 | -XX:MaxGCPauseMillis=100 | 设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值。 |
-XX:+UseAdaptiveSizePolicy | 设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低响应时间或者收集频率等,此值建议使用并行收集器时,一直打开 | |
-XX:G1HeapRegionSize | 指定Region大小(必须是2的倍数,1M、2M、4M到32M。一般自己计算即可) | |
-XX:G1NewSizePercent | 新生代初始内存,默认为堆内存的5% | |
-XX:G1MaxNewSizePercent | 新生代最高内存,默认为堆内存的60% | |
-XX:InitiatingHeapOccupancyPercent | 到达老年代占据堆内存的百分比时,会触发新生代和老年代的混合垃圾回收,默认45% | |
-XX:G1MixedGCCountTarget | 多次混合回收,默认8次 | |
-XX:G1HeapWastePercent | 停止结束混合回收条件,堆内存有5%空闲Region 默认5 | |
-XX:G1MixedGCLiveThresholdPercent | 每个Region空间存活对象低于85%时才会回收,默认85 | |
Metaspace | -XX:MetaspaceSize | 是分配给类元数据空间(以字节计)的初始大小(Oracle逻辑存储上的初始高水位,the initial high-water-mark ),此值为估计值。MetaspaceSize的值设置的过大会延长垃圾回收时间。垃圾回收过后,引起下一次垃圾回收的类元数据空间的大小可能会变大。 |
-XX:MaxMetaspaceSize | 是分配给类元数据空间的最大值,超过此值就会触发Full GC,此值默认没有限制,但应取决于系统内存的大小。JVM会动态地改变此值。 | |
-XX:MinMetaspaceFreeRatio | 表示一次GC以后,为了避免增加元数据空间的大小,空闲的类元数据的容量的最小比例,不够就会导致垃圾回收。 | |
-XX:MaxMetaspaceFreeRatio | 表示一次GC以后,为了避免增加元数据空间的大小,空闲的类元数据的容量的最大比例,不够就会导致垃圾回收。 |
相关文章:
垃圾回收机制--GC 垃圾收集器--JVM调优-面试题
1.触发垃圾回收的条件 新生代 Eden区域满了,触发young gc (ygc)老年代区域满了,触发full gc (fgc)通过ygc后进入老年代的平均大小大于老年代的可用内存,触发full gc(fgc).程序中主动调用的System.gc()强制执行gc,是full gc,但是不必然执行。…...
Java基础知识总结(29)
Java虚拟机 运行时数据区 程序计数器 方法区:Java 8以后没有方法区,改为了元空间(MetaSpace) 虚拟机栈 堆 本地方法栈 程序计数器 它可以看作是当前线程所执行的字节码的行号指示器。在Java虚拟机的概念模型里,…...
vue js金额转中文
在Vue.js项目中,实现金额转中文的功能通常涉及编写一个JavaScript方法来处理数字转换逻辑,并在Vue组件中调用该方法。下面是一个基本的示例,展示如何在Vue组件中定义一个计算属性或方法来实现这一功能: /*** 思路: …...
《QT实用小工具·二》图片文字转base64编码
1、概述 源码放在文章末尾 base64编码转换类 图片转base64字符串。base64字符串转图片。字符转base64字符串。base64字符串转字符。后期增加数据压缩。Qt6对base64编码转换进行了重写效率提升至少200%。 下面是demo演示: 项目部分代码如下所示: #ifn…...
Django安装及第一个项目
1、安装python C:\Users\leell>py --version Python 3.10.6 可以看出我的环境python的版本3.10.6,比较新 2、 Python 虚拟环境创建 2.1 官网教程 目前,有两种常用工具可用于创建 Python 虚拟环境: venv 在 Python 3.3 及更高版本中默…...
专升本-物联网
物联网(IOT,Internet of things) 体系结构: 感知层(感知执行层) 网络层 应用层 基本特征: 全面感知 可靠传输 智能处理 作用: 信息采集、转换、收集 信息传递和处理 数据…...
二叉树的遍历C语言
二叉树作为FDS课程最核心的数据结构之一,要求每个人都掌握! 这是一道简单的二叉树问题! 我们将给出一颗二叉树,请你输出它的三种遍历,分别是先序遍历,中序遍历,后序遍历! 输入格式…...
PostgreSQL到Doris的迁移技巧:实时数据同步新选择!
PostgreSQL可以说是目前比较抢手的关系型数据库了,除了兼具多样功能和强大性能之外,还具备非常优秀的可扩展性,更重要的是它还开源,能火不是没有理由的。 虽然PostgreSQL很强大,但是它也有短板,相对于专业…...
【三维】关于万向节锁的直白解释
1. 分析理解 万向节长什么样子,请参考这篇文章中的图片:https://zhuanlan.zhihu.com/p/42519819。 看了很多篇解释性的文章,没怎么看懂。因为我个人最关注的问题点在于: 现实物体旋转为什么没有所谓的万向节锁的bug,…...
程序员的修养 - 变量
变量几乎代码程序程序 中最基础的组成单元,程序员几乎无时无刻都在接触变量。但你对变量的理解真的足够吗? 首先,什么是变量?! 第一层理解:一个可以改变的量,区别于常量,用户可以修…...
判断一个元素是否在可视区域中
文章目录 一、用途二、实现方式offsetTop、scrollTop注意 getBoundingClientRectIntersection Observer创建观察者传入被观察者 三、案例分析 参考文献 一、用途 可视区域即我们浏览网页的设备肉眼可见的区域,如下图 在日常开发中,我们经常需要判断目标…...
【Monero】Wallet RPC | Wallet CLI | 门罗币命令行查询余额、种子、地址等命令方法教程
ubuntu22.04 首先在运行daemon,详细安装运行教程可参考:The Monero daemon (monerod) ./monerodWallet CLI run ./monero-wallet-cli如果还没有钱包就根据提示创建钱包即可 输入密码 查询余额 balance查询种子 seed其他可执行命令操作࿱…...
FPGA----ZCU106的petalinux 2019.1使用USB传输数据
1、实际项目中需要用到开发板的串口进行数据交互,之前讲的几节只是启动了网口(如下链接)。因此,本次给大家带来的官方自带串口例程的使用方法,本文的vivado工程和下述连接一样,PL端什么配置都没有。 FPGA-…...
备考ICA----Istio实验10---为单个主机配置TLS Istio Ingress Gateway实验
备考ICA----Istio实验10—为单个主机配置 TLS Istio Ingress Gateway实验 1. 环境准备 部署httpbin kubectl apply -f istio/samples/httpbin/httpbin.yaml 2. 证书生成 2.1 生成根证书 生成根证书keyfile和crt文件 mkdir example_certs_root openssl req -x509 -sha256 …...
【4】单链表(有虚拟头节点)
【4】单链表(有虚拟头节点) 1、虚拟头节点2、构造方法3、node(int index) 返回索引位置的节点4、添加5、删除6、ArrayList 复杂度分析(1) 复杂度分析(2) 数组的随机访问(3) 动态数组 add(E element) 复杂度分析(4) 动态数组的缩容(5) 复杂度震荡 7、单链…...
html第二次作业
骨架 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, initi…...
Android客户端自动化UI自动化airtest从0到1搭建macos+脚本设计demo演示+全网最全最详细保姆级有步骤有图
iOS客户端自动化UI自动化airtest从0到1搭建macosdemo演示-CSDN博客 一、基础环境 1. 安装jdk 选择jdk8 如果下载高版本 可能不匹配会失败 下载.dmg文件 苹果电脑 | macOS | jdk1.8 | 环境变量配置_jdk1.8 mac-CSDN博客 Java Downloads …...
基于单片机的自动浇灌系统的设计
本文设计了一款由单片机控制的自动浇灌系统。本设计的硬件电路采用AT89C51单片机作为主控芯片,采用YL-69土壤湿度传感器检测植物的湿度。通过单片机将采集湿度值与设定值分析处理后,控制报警电路和水泵浇灌电路的开启,从而实现植物的自动浇灌。 1 设计目的 随着生活水平的…...
WebStorm 与 VSCode 对比分析
WebStorm 与 VSCode 对比分析 1. 引言 简述WebStorm和VSCode的普及和重要性 WebStorm和Visual Studio Code(VSCode)是当前最受欢迎的代码编辑器之一,它们在现代软件开发中扮演着至关重要的角色。WebStorm,由JetBrains开发,是一个强大的IDE,特别受JavaScript开发者的欢…...
git命令-项目使用
项目中用到的git命令,记录下来,后续项目可以直接用 配置命令 一次性设置: git config --global user.name "Your Name" git config --global user.email "youremailaddress.com"git config --global alias.pl "pu…...
python安装删除以及pip的使用
目录 你无法想象新手到底会在什么地方出问题——十二个小时的血泪之言! 问题引入 python modify setup 隐藏文件夹 环境变量的配置 彻底删除python 其他零碎发现 管理员终端 删不掉的windous应用商店apps 发现问题 总结 你无法想象新手到底会在什么地方…...
7、鸿蒙学习-共享包概述
HarmonyOS提供了两种共享包,HAR(Harmony Archive)静态共享包,和HSP(Harmony Shared Package)动态共享包。 HAR与HSR都是为了实现代码和资源的共享,都可以包含代码、C库、资源和配置文件…...
亚马逊测评新策略:解决底层环境防关联,提升下单成功率
对于做测评的环境系统,确保稳定性和成功率是非常重要的。市面上有各种环境方案,如虚拟机、模拟机、gcs、云手机、VPS等。然而,这些方案不仅成本高,而且成功率很低。因此,一个好的环境系统是成功的基础。 亚马逊平台的…...
容器和注解开发
1.创建容器的两种方式 //1.加载类路径下的配置文件//ApplicationContext ctx new ClassPathXmlApplicationContext("applicationContext.xml"); //2.从文件系统下加载配置文件(绝对路径) ApplicationContext ctx new FileSystemXmlApplicationContex…...
有趣且重要的JS知识合集(21)浏览器内置对象讲解之Dom篇
1、Dom 1.1、概念 Document Object Model(文档对象模型), 整个WEB页面, 所有的Dom元素都在Document整个文档里。DOM就是把整个文档页面当做一个对象进行操作, document 下 包含了 根据 html 创建 的 Dom 对象, 这个DOM对象, 以树形结构展示, 即DOM树 …...
3.两数相加 - 链表
文章目录 题目简介题目解答代码: 题目链接 大家好,我是晓星航。今天为大家带来的是 两数相加 相关的讲解!😀 题目简介 题目解答 通过题目给的第一个示例来解析 图解如下: l1的2和l2的5首先相加变为7 这里相加结果为7…...
iptables 与 firewalld 防火墙
iptables iptables 是一款基于命令行的防火墙策略管理工具 四种防火墙策略: ACCEPT(允许流量通过) 流量发送方会看到响应超时的提醒,但是流量发送方无法判断流量是被拒绝,还是接收方主机当前不在线 REJECT(…...
Taskflow:异步任务(Asynchronous Tasking)
简单使用 tf::Executor 提供了异步执行Task的操作tf::Executor::async,并返回Future,用于保留该函数调用的结果。 #include <taskflow/taskflow.hpp>void print_str(char const* str) {std::cout << str << std::endl; }int main() …...
学习鸿蒙基础(9)
目录 一、鸿蒙国际化配置 二、鸿蒙常用组件介绍 三、鸿蒙像素单位介绍 四、鸿蒙布局介绍 1、Row与Column线性布局 2、层叠布局-Stack 3、弹性布局 4、栅格布局 5、网格布局 一、鸿蒙国际化配置 base目录下为默认的string。en_US对应美国的。zh_CN对应中国的。新增一个s…...
spring boot的小数位丢失.00 或者.0
1、背景 在使用spring boot时,前端的界面展示的数据是2 ,在数据库中存储的是小数。但是导出Excel的时候数据是 2.00 。奇了怪了为啥会不一样,数据都是一样的没有做过处理。 2、排查问题 经过层层的debug 发现数据库返回的数据是2.00&#x…...
腾讯大浙网 网站开发/个人模板建站
jQuery的用途: 一. 访问和操作DOM元素 利用jQuery可以方便地获取和修改页面中的指定元素,如:添加,删除商品,留言,个人信息等。 二. 控制页面样式 用jQuery可以很便捷地控制页面的CSS文件,用jQ…...
做分销网站系统/国外推广网站有什么
也就是说,拉勾网岗位数据请求的网址是不变的,改变的是表单数据,表单数据随着页数改变,请求方式为POST,这里没办法在Pyspider里用循环遍历来获取每一页的数据。也许是我对Pyspider框架了解的不够,还达不到得…...
开发网站 语言/做外贸用什么软件找客户
我们都知道SSD拥有比HDD更快的读写速度,但SATA总线标准却拖累了SSD性能的发挥。好消息是,如今越来越多的笔记本都配备了支持PCI-E总线标准的M.2插槽,这就让更高速的NVMeSSD有了用武之地。 看到这里可能很多童鞋已经泛起了迷糊:啥…...
阿里巴巴国际网站怎么做/美国今天刚刚发生的新闻
--带参数的游标--DECLAREdept_code emp.deptno%TYPE; --声明列类型变量三个emp_code emp.empno%TYPE;emp_name emp.ename%TYPE;CURSOR emp_cur(deptparam NUMBER) ISSELECT empno, ename FROM EMP WHERE deptno deptparam; --声明显示游标BEGINdept_code : &部门编号; --请…...
社交app开发成本预算表/优化网站的方法有哪些
实现了 出/入 分别计数; - 检测类别:行人、自行车、小汽车、摩托车、公交车、卡车。 -支持yolov5s.pt yolov5x.pt yolov5m.pt yolov5l.pt模型...
做货代的可以在哪些网站打广告/建站平台哪个好
最近在使用遇到一个问题需要把csv格式的文件转成xls,随便新建一个excel,然后打开,选择“开发工具”,找到下图“宏”,如果跟下图一样的话就需要先启用宏,启用之后可以直接把下面的代码直接复制到代码区&…...