首页 > 编程语言 >抓取java堆栈失败的思考-Safepoint等的学习

抓取java堆栈失败的思考-Safepoint等的学习

时间:2024-01-03 14:05:21浏览次数:39  
标签:java 抓取 线程 jvm 堆栈 GC Safepoint

抓取java堆栈失败的思考-Safepoint等的学习


背景

前期解决问题都是靠抓取进程堆栈
jstack,后者是jmap到内存dump的方式来进行分析.

最近连续有两个比较大的项目出现了抓取dump/stack 失败的情况. 
具体原因可能还不太一样. 周末再翻找之前的资料时猜到了可能得几个原因.
想总结一下. 

因为自己并没有看过JVM的源码, 所以可能会是错误的. 
希望能够再后续的工作中去求证或者是证伪

后面也想描述一下一个简单的解决思路. 其实之前也总结过.

jvm的堆栈信息的获取.

jstack -l $pid  查看运行的堆栈信息.
jmap -heap $pid 查看堆的简要信息.
jmap -histo $pid 查看堆中对象的占用情况.
jmap -dump:format=b,file=/root/somefile $pid  
获取dump文件, 注意需要使用 IBM的mat等工具进行分析. 
这些操作得到的结果逐渐复杂, 并且消耗的时间和资源也越来越多.

关于抓取的过程

JVM在运行期间, 其实是有很多线程的
如果无法内部查看, 可以使用 top -Hp $pid 的方式是简单查看一下大体的线程信息. 

这里的线程数,其实会包含 java的守护线程, GC线程, 线程池线程,以及编译器等线程. 

使用java工具进行抓取时, 理论上是要求 jvm里面的线程都到达 safepoint才可以的. 
但是某些情况下可能无法到达safepoint ,可能就会出现严重的问题. 导致抓取失败. 

如果可以到达, 那么就可以直接进进行堆栈的快照以及信息展示. 
所以需要注意,不要随便进行 jstack 等堆栈信息的获取,会触发一次 STW, 如果safepoint的到达比较慢
会出现严重的卡顿现象.

关于safepoint

Java虚拟机HotSpot的实现中,使用一组称为OopMap的数据结构来存放对象引用,从而可以快速且准确的完成GC Root扫描。
但程序执行的过程中,引用关系随时都可能发生变化,而HotSpot虚拟机只会在特殊的指令位置才会生成OopMap来记录引用关系,
这些位置便被称为Safepoint。
换句话说,就是在Safepoint这个点上,虚拟机对于调用栈、寄存器等一些重要的数据区域里什么地方包含了什么引用是十分清楚的,
这个时候是可以很快完成GC Roots的扫描和可达性分析的。
HotSpot会在所有方法的临返回之前,以及所有Uncounted loop的循环回跳之前放置Safepoint。
当需要GC时候,虚拟机会首先设置一个标志,然后等待所有线程进入Safepoint,
但是不同线程进入Safepoint的时间点不一样,先进入Safepoint的线程需要等待其他线程全部进入Safepoint,所以Safepoint是会导致STW的。

抓取堆栈失败的两种情况

1. 第一个是K8S项目, 因为podpidslimit的问题, jvm无法再生成一个新的线程, 导致抓取失败. 
   这个问题比较好解释, 因为系统的线程资源耗尽, 导致无法工作. 
   解决问题的思路也比较简单. 修改podpidslimit 或者是修改线程数的数量, 避免大量占用就可以了 

2. 第二个就是昨天遇到的, 怀疑跟小米科技的问题一样. 
   怀疑产品有一个 : Counted loop
   解释为: JVM认为比较短的循环,所以不会放置Safepoint,比如用int作为index的循环。
   怀疑产品里面有一个 int类型的比较大的循环, 一直在占用CPU. jvm又无法再可数循环结束之前插入safepoint
   导致除了GC线程和这个工作线程之外,大家都在等他俩到达Safepoint. 
   同事处于STW的状态, 导致异常无法提供服务 并且也因为无法到达saftpoint
   导致抓取线程堆栈信息失败.

关于解决思路

使用gdb 在操作系统层抓取core文件
然后使用jvm 解析core dump文件为 java可读文件
在使用 mat进行分析
在不可能时提供一种可能得解决思路.



标签:java,抓取,线程,jvm,堆栈,GC,Safepoint
From: https://blog.51cto.com/u_11529070/9084334

相关文章

  • JAVA开发工具Eclipse和MyEclipse
    Eclipse和MyEclipse都是广泛使用的集成开发环境(IDE),主要用于Java语言的开发,但也有其他插件支持如C++和Python等其他计算机语言的开发。两者之间的主要区别在于Eclipse是开源的,而MyEclipse则是基于Eclipse的商业版本。    Eclipse:Eclipse最初是由IBM公司开发的替代商业软......
  • java接口自动化系列(11):断言请求结果
     添加工具类AssertUtil.javapackagecom.qzcsbj.autotest.utils;importcom.jayway.jsonpath.Configuration;importcom.jayway.jsonpath.JsonPath;importorg.testng.Assert;/***@公众号:全栈测试笔记*@描述:<>*/publicclassAssertUtil{//断言字段......
  • java接口自动化系列(07):解析并执行初始化sql
     添加pom依赖连接操作数据库<!--https://mvnrepository.com/artifact/mysql/mysql-connector-java--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><v......
  • java接口自动化系列(03):创建自动化框架项目
     创建maven项目 输入GroupId:com.qzcsbj输入ArtifactId:apiJavaAutoTest 输入Projectname:apiJavaAutoTest 配置maven修改Mavenhomedirectory和Usersettingsfile(settings.xml文件配置了阿里云镜像地址) 添加pom依赖testng<!--https://mvnrepository.com/artifact/org.testng......
  • 无涯教程-Java 正则 - X{n}+ 匹配函数
    PossesiveQuantifier[X{n}+]与存在的X个精确匹配n次。X{n}+-示例packagecom.learnfk;importjava.util.regex.Matcher;importjava.util.regex.Pattern;publicclassPossesiveQuantifierDemo{privatestaticfinalStringREGEX="T{2}+";privatestat......
  • 无涯教程-Java 正则 - X++ 匹配函数
    PossesiveQuantifier[X++]与X匹配一次或多次。X++-示例packagecom.learnfk;importjava.util.regex.Matcher;importjava.util.regex.Pattern;publicclassPossesiveQuantifierDemo{privatestaticfinalStringREGEX="T++";privatestaticfinalS......
  • java调用rust 共享库的一些方法简单说明
    java与rust的调用,核心还是基于jni进行处理,rust社区实现了不少方便的工具可以提供rust到c的处理(比如生成头文件)以下是整理的一些资料,方便学习几个不错的包jni-rs 目前还在活跃更新中,同时github的start也比较多,同时不少开源软件在用,比如questdbrobusta 一个比较新的项目,使用......
  • 无涯教程-Java 正则 - X*+ 匹配函数
    PossesiveQuantifier[X*+]匹配X出现零次或多次。X*+-示例packagecom.learnfk;importjava.util.regex.Matcher;importjava.util.regex.Pattern;publicclassPossesiveQuantifierDemo{privatestaticfinalStringREGEX="T*+";privatestaticfinal......
  • javascript的Map和Set概念以及区别和使用场景
    Map和SetJavaScript的默认对象表示方式{}可以视为其他语言中的Map或Dictionary的数据结构,即一组键值对。但是JavaScript的对象有个小问题,就是键必须是字符串。但实际上Number或者其他数据类型作为键也是非常合理的。MapMap是一组键值对的结构,具有极快的查找速度。举个例子,假设要根......
  • 25个JavaScript One-Liner让你更专业
    今天我们分享一些单行代码技巧,了解这些技巧,可以提升我们的工作效率,现在,我们一起来看一下今天的这些单行代码技巧吧。数组1.检查变量是否是数组constisArray=Array.isArray(arr);constisArray=arrinstanceofArray;2.数字数组的和constsum=(arr)=>arr.reduce((a,b)......