linux gc日志分析工具,JVM GC日志分析及性能优化

从新认知JVM:

经过前面从Class文件到类装载器,再到运行时数据区的过程。咱们画张图展现了JVM的大致物理结构图。html

1dbd36f661f8b2c9fe1373952b5b949e.png

GC优化:

内存被使用了以后,不免会有不够用或者达到设定值的时候,就须要对内存空间进行垃圾回收。java

GC是由JVM自动完成的,根据JVM系统环境而定,因此时机是不肯定的。 固然,咱们能够手动进行垃圾回收,好比调用System.gc()方法通知JVM进行一次垃圾回收,可是具体什么时刻运行也没法控制。也就是说System.gc()只是通知要回收,何时回收由JVM决定。 可是不建议手动调用该方法,由于消耗的资源比较大。通常如下几种状况会发生垃圾回收算法

当Eden区或者S区不够用了

老年代空间不够用了

方法区空间不够用了

System.gc()

GC日志文件:

首先回顾一下各个垃圾收集器对应的代。性能优化

6c52494fc7e8b73ae3aaec8172be013c.png

ParallelGC Log:

要想分析日志的信息,得先拿到GC日志文件才行,因此得先配置一下,以前也看过这些参数。而后启动项目并发

-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps-Xloggc:gc.log

到项目根目录下找到 gc.log 文件打开:能够看到默认使用的是ParallelGCoracle

89c2f8947235ab73f45c57895ba1714f.png

注意 若是回收的差值中间有出入,说明这部分空间是Old区释放出来的app

CMS GC  Log:

停顿时间优先,参数设置:-XX:+UseConcMarkSweepGC -Xloggc:cms-gc.logide

e7d9eff99e89b17b271ab1e4018d9264.png

G1日志:

停顿时间优先,参数设置:-XX:+UseG1GC -Xloggc:g1-gc.log高并发

19962b2fcd40b40b885e5b7a0c71441c.png

-XX:+UseG1GC  # 使用了G1垃圾收集器

# 何时发生的GC,相对的时间刻,GC发生的区域young,总共花费的时间,0.00478s,

# Itis a stop-the-world activity and all

# the application threads are stopped at a safepoint duringthistime.2019-12-18T16:06:46.508+0800: 0.458: [GC pause (G1 Evacuation Pause) (young),0.0047804secs]

# 多少个垃圾回收线程,并行的时间

[Parallel Time:3.0 ms, GC Workers: 4]

# GC线程开始相对于上面的0.458的时间刻

[GC Worker Start (ms): Min:458.5, Avg: 458.5, Max: 458.5, Diff: 0.0]

# This gives us the time spent by each worker thread scanning the roots

# (globals, registers, thread stacks and VM data structures).

[Ext Root Scanning (ms): Min:0.2, Avg: 0.4, Max: 0.7, Diff: 0.5, Sum: 1.7]

# Update RS gives us the time each thread spentinupdating the Remembered Sets.

[Update RS (ms): Min:0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]

...

常见GC日志文件分析工具:

gceasy:

GC Easy是一款在线的可视化工具,易用、功能强大。官网 :https://gceasy.io 。能够比较不一样的垃圾收集器的吞吐量和停顿时间,好比打开cms-gc.log和g1-gc.log

175a7108c566a3c252d0c4540f657e29.png

4a5cb65f4a47b2e390f3f6842bb6560f.png

GCViewer:

须要下载 gcviewer-1.36-SNAPSHOT.jar ,而后运行这个jar。

9e7d86df0cb371067da9ae923e1b7583.png

G1调优与最佳指南:

50%以上的堆被存活对象占用

对象分配和晋升的速度变化很是大

垃圾回收时间比较长

使用G1GC垃圾收集器: -XX:+UseG1GC 。修改配置参数,获取到gc日志,使用GCViewer分析吞吐量和响应时间

Throughput    Min Pause    Max Pause   Avg Pause    GC count99.16%       0.00016s     0.0137s     0.00559s      12

调整内存大小再获取gc日志分析

-XX:MetaspaceSize=100M-Xms300M-Xmx300M

好比设置堆内存的大小,获取到gc日志,使用GCViewer分析吞吐量和响应时间

Throughput    Min Pause    Max Pause   Avg Pause    GC count98.89%       0.00021s     0.01531s    0.00538s      12

启动并发GC时堆内存占用百分比:-XX:InitiatingHeapOccupancyPercent=45 G1用它来触发并发GC周期,基于整个堆的使用率,而不仅是某一代内存的使用比例。值为 0 则表示“一直执行GC循环)'. 默认值为 45 (例如, 所有的 45% 或者使用了45%).好比设置该百分比参数,获取到gc日志,使用GCViewer分析吞吐量和响应时间

Throughput    Min Pause    Max Pause   Avg Pause    GC count98.11%       0.00406s    0.00532s    0.00469s     12

最佳指南:

不要手动设置新生代和老年代的大小,只要设置整个堆的大小:G1收集器在运行过程当中,会本身调整新生代和老年代的大小实际上是经过adapt代的大小来调整对象晋升的速度和年龄,从而达到为收集器设置的暂停时间目标若是手动设置了大小就意味着放弃了G1的自动调优不断调优暂停时间目标通常状况下这个值设置到100ms或者200ms都是能够的(不一样状况下会不同),但若是设置成50ms就不太合理。暂停时间设置的过短,就会致使出现G1跟不上垃圾产生的速度。最终退化成Full GC。因此对这个参数的调优是一个持续的过程,逐步调整到最佳状态。暂停时间只是一个目标,并不能老是获得知足。

使用-XX:ConcGCThreads=n来增长标记线程的数量,IHOP(InitiatingHeapOccupancyPercent)若是阀值设置太高,可能会遇到转移失败的风险,好比对象进行转移时空间不足。若是阀值设置太低,就会使标记周期运行过于频繁,而且有可能混合收集期回收不到空间。IHOP值若是设置合理,可是在并发周期时间过长时,能够尝试增长并发线程数,调高ConcGCThreads。

MixedGC 混合回收调优:mixed GC就是把一部分老年区的region加到Eden和Survivor from的后面,合起来称为collection set, 就是将被回收的集合,下次mixed GC evacuation把他们全部都一并清理。

-XX:InitiatingHeapOccupancyPercent //设置触发标记周期的Java堆占用阈值,默认值为45。-XX:G1MixedGCLiveThresholdPercent //设置在标记周期完成以后混合收集的数量,以维持old region(也就是老年代)中,最多有G1MixedGCLiveThresholdPercent的存活对象。默认值为8-XX:G1MixedGCCountTarger //一个混合收集周期中包含多少次混合收集-XX:G1OldCSetRegionThresholdPercent //一次混合收集中被收集的old region数量的上线,默认值是整个堆的10%

适当增长堆内存大小

高并发场景分析:

以下图,当一个订单服务以每秒3000单的速度请求,而后请求的订单服务的集群数为3。假设每次请求产生的订单的实例在内存中所占大小为1KB,具体的计算能够根据对象头内的内容进行计算,此时订单服务可能还会调用其余的服务,此过程也会产生对象,那么扩大20倍,此时每一个节点每秒点单服务会产生20MB的内存占用,假设堆内存为4000MB,那么Young为1333MB. 65秒后这个Young区便会满触发Minor GC。对象晋升,步入老年代,这样的速率会致使老年代的内存很快就满了,就会触发Major GC,Metaspace 区域也会频繁的GC,这样子会触发Full GC。那么这个时候咱们能够适当的增长 Young区大小,调整Young区跟Old区的比例。

865f0d6f8ce43ed53692f4bca90bb159.png

JVM性能优化指南:

90cae626c3497b6b442e2e697bba91dc.png

常见问题思考:

内存泄漏与内存溢出的区别?:内存泄漏:对象没法获得及时的回收,持续占用内存空间,从而形成内存空间的浪费。内存溢出:内存泄漏到必定的程度就会致使内存溢出,可是内存溢出也有多是大对象致使的。

young gc会有stw吗?无论什么 GC,都会有 stop-the-world,只是发生时间的长短。

major gc和full gc的区别?:major gc指的是老年代的gc,而full gc等于young+old+metaspace的gc。

G1与CMS的区别是什么?:CMS 用于老年代的回收,而 G1 用于新生代和老年代的回收。G1 使用了 Region 方式对堆内存进行了划分,且基于标记整理算法实现,总体减小了垃圾碎片的产生。

什么是直接内存?:直接内存是在java堆外的、直接向系统申请的内存空间。一般访问直接内存的速度会优于Java堆。所以出于性能的考虑,读写频繁的场合可能会考虑使用直接内存。

不可达的对象必定要被回收吗?:即便在可达性分析法中不可达的对象,也并不是是“非死不可”的,这时候它们暂时处于“缓刑阶段”,要真正宣告一个对象死亡,至少要经历两次标记过程;可达性分析法中不可达的对象被第一次标记而且进行一次筛选,筛选的条件是此对象是否有必要执行 finalize 方法。当对象没有覆盖 finalize 方法,或 finalize 方法已经被虚拟机调用过期,虚拟机将这两种状况视为没有必要执行。被断定为须要执行的对象将会被放在一个队列中进行第二次标记,除非这个对象与引用链上的任何一个对象创建关联,不然就会被真的回收。

方法区中的无用类回收:方法区主要回收的是无用的类,那么如何判断一个类是无用的类的呢?断定一个常量是不是“废弃常量”比较简单,而要断定一个类是不是“无用的类”的条件则相对苛刻许多。类须要同时满足下面 3 个条件才能算是 “无用的类” :该类全部的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例。加载该类的 ClassLoader 已经被回收。该类对应的 java.lang.Class 对象没有在任何地方被引用,没法在任何地方经过反射访问该类的方法。虚拟机能够对知足上述 3 个条件的无用类进行回收,这里说的仅仅是“能够”,而并非和对象同样不使用了就会必然被回收。

不一样的引用:JDK1.2之后,Java对引用进行了扩充:强引用、软引用、弱引用和虚引用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值