原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。

简介

上次解决了GC长耗时问题后,系统果然平稳了许多,这是之前的文章《GC耗时高,原因竟是服务流量小?》
然而,过了一段时间,我检查GC日志时,又发现了一个GC问题,如下:
image_2023-02-04_20230204143644
从这个图中可以发现,我们GC有一些尖峰,有时会突然有大量的内存分配。

查看GC日志,发现有大对象分配的记录,如下:

$ grep 'concurrent humongous allocation' gc.log | awk 'match($0,/allocation request: (w+) bytes/,a){print a[1]}' |sort -nr
1941835784
1889656848

image_2023-02-04_20230204143322
可以看到,一次大对象分配,分配大小竟然有1.9G,这谁能抗得住啊!

async-profiler定位大对象分配

上面提到的文章介绍过,使用async-profiler可以很容易的定位大对象分配的调用栈,方法如下:

./profiler.sh start --all-user -e G1CollectedHeap::humongous_obj_allocate -f ./humongous.jfr jps

然后使用jmc打开humongous.jfr文件,调用栈如下:
image_2023-02-04_20230204180005

这是在做thrift反序列化操作,调用了TCompactProtocol.readDouble方法,方法代码如下:
image_2023-02-04_20230204144842
可是,这里只创建了8字节的数组,怎么也不可能需要分配1.9G内存吧,真是奇了怪了!

经过一番了解,这是因为async-profiler是通过AsyncGetCallTrace来获取调用栈的,而AsyncGetCallTrace获取的栈有时是不准的,Java社区有反馈过这个问题,至今未解决。
image_2023-02-04_20230204171551
问题链接:https://bugs.openjdk.org/browse/JDK-8178287

寻找其它tracer

linux上有很多内核态的tracer,如perf、bcc、systemtap,但它们都需要root权限,而我是不可能申请到这个权限的

内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/codelogs/p/17092141.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!