本文主要是介绍FullGC的Demo与原因定位,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
作为平台开发人员,经常要为用户定位应用(如Flink、Spark等)的线上问题,出现频率较高的就是任务实现问题,出现FullGC,从而导致数据处理速度下降或是OOM等问题,下面简单记录、分享下定位过程。
内容如下:
- Main方法,复现FullGC场景
- 定位FullGC的步骤
Main方法,复现FullGC场景
无论是Flink、Spark还是web应用,都会有GC监控或日志打印(Gc日志参数控制),一旦出现,就需要排查原因,定位哪个对象太大,导致FullGC太频繁。
下面的Main可以直接运行,运行过程中会不断在堆内存中创建Person对象,触发FullGC:
package com.wj.jvm.gc;import java.util.ArrayList;
import java.util.List;/*** 引发FullGC** @author wj*/
public class FullGC {private static long counter = 0;private static List<Object> list = new ArrayList<>();public static void main(String[] args) {int availableProcessors = Runtime.getRuntime().availableProcessors();for (int i = 0; i < availableProcessors; i++) {new Thread(() -> {while (true) {list.add(Person.newInstance("cmy", 29, "天润城"));list.add(Person.newInstance("wj", 28, "天润城2"));counter += 2;System.out.println("counter : " + counter);}}).start();}}
}class Person {private String name;private Integer age;private String address;private String name2;private Integer age2;private String address2;private Person(String name, Integer age, String address) {this.name = name;this.age = age;this.address = address;}static Object newInstance(String name, Integer age, String address) {Person person = new Person(name, age, address);person.name2 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";person.age2 = 33333;person.address2 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";return person;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", address='" + address + '\'' +", name2='" + name2 + '\'' +", age2=" + age2 +", address2='" + address2 + '\'' +'}';}
}
参考:
- FullGC触发条件:https://blog.csdn.net/yuxxz/article/details/89432786
- Java GC 日志详解(图):https://www.jianshu.com/p/ade514d7c56b
定位FullGC的步骤
1.登录到App所在机器
结合具体的App应用场景,登录到指定机器上,如Flink部署到Yarn上,需要从namenode节点跳转至Container。
2. 找到App进程号
- 方式一: jps -l
直接使用java命令,查询当前机器上所有java进程ID - 方式二:ps -ef | grep application_1556437712190_212447 | grep -v grep
根据应用的appId查询进程ID
3.查看GC信息
- jstat -gcutil -h 20 pid 1000 20000
示例结果如下:
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 36 187.562 195.246
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 36 187.562 195.246
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 37 192.986 200.670
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 37 192.986 200.670
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 37 192.986 200.670
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 37 192.986 200.670
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 37 192.986 200.670
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 38 198.437 206.121
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 38 198.437 206.121
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 38 198.437 206.121
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 38 198.437 206.121
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 38 198.437 206.121
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 38 198.437 206.121
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 39 203.949 211.633
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 39 203.949 211.633
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 39 203.949 211.633
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 39 203.949 211.633
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 39 203.949 211.633
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 40 209.629 217.313
0.00 0.00 100.00 100.00 94.85 85.10 39 7.684 40 209.629 217.313
每秒输出一次gc状态,从结果可以看出,每5秒左右即出现FGC。
关于jstat -gcutil的指令用法和结果分析可参考:https://blog.csdn.net/zhaozheng7758/article/details/8623549
4.FullFC较为频繁,查看gc的对象
- jmap -histo:live 6812 | head -10
示例结果如下:
num #instances #bytes class name
----------------------------------------------
1: 9221275 368851000 com.wj.jvm.gc.Person
2: 1083 258508144 [Ljava.lang.Object;
3: 9221531 147544496 java.lang.Integer
4: 6844 728632 [C
5: 6693 160632 java.lang.String
从结果可以看出,导致FGC的大对象就是com.wj.jvm.gc.Person导致的。
关于jmap的用法可以参考:https://www.cnblogs.com/kongzhongqijing/articles/3621163.html
这篇关于FullGC的Demo与原因定位的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!