11 月 19 - 20 日 Apache Pulsar 社区年度盛会来啦,立即报名! 了解详情
写点什么

谜!JVM 为何僵死

  • 2019-09-20
  • 本文字数:1931 字

    阅读完需:约 6 分钟

谜!JVM为何僵死

前不久有兄弟部门的同事找到我,说他们有一个 Java 应用偶尔会莫名僵死、无响应、同时有个 CPU 核心占用 100%,不稳定复现。希望我协助看看是什么原因。



现场

如果仅仅只看到“僵死”,“无响应”这类描述,可能马上想到 GC 可能有问题,又看到 CPU 占用 100%,又可能是存在死循环,实际情况是怎么样的呢?


咱们要用证据来说话,所谓证据其实就是故障现场,包括但不限于:GC 日志、线程 dump、堆 dump、业务日志、CPU、内存、磁盘等资源使用情况等等。


1. thread dump

就这个问题而言,因为 CPU 占用飙到 100%,所以我们先通过线程 dump 出来的堆栈信息看看线程都在干什么。 一般情况下我们常用 jstack 命令来获取线程 dump。同事先使用了如下命令,结果命令也僵死无响应:



去掉-l 后才 dump 出了咱们的第一个证据, 内容大致如下:



查看以上信息,发现了一个很奇怪的现象,除了监听端口的主线程外,所有的线程都处于 BLOCKED 状态,并且调用栈上没有任何业务代码的痕迹。但是为什么 CPU 会占用 100%呢?


一个合理的推测是存在其他正在执行本地方法的线程,然后我让同事分别用



查看到占用 CPU100%的线程调用栈如下:



这个调用栈信息,看起来像是在遍历类结构的时候出现了死循环,目测可能是触发了 JVM 的隐藏 BUG


2.GC STAT

除了查看 GC 日志外,一般我们还经常通过 jstat 来查看 gc 情况,比如:




注意看 M 的那一列,代表 Metaspace 的使用已经接近 100%,而 Metaspace 是从 java8 开始引入,替代过去的 PermGen 空间(永久带),用来存放类的元数据等信息


3.JVM 启动参数

精简后的 JVM 启动参数如下:



从启动参数可以看出来:


  1. jdk 版本是 HotSpot 8u40

  2. 指定了 MaxMetaspaceSize

  3. 使用了 CMS GC 算法、增量模式

  4. 指定了 noclassgc


分析

处理线上问题,最要紧的一定是先尽快恢复服务,减少业务损失。 从之前的信息来推测,大概率是触发了 JVM 的隐藏 BUG, 从历史来看,hotspot bugfix 的速度还是不错的,同事先升级到最新的 JDK 版本尝试恢复服务,咱们再接下来分析原因。


MaxMetaspaceSize


顾名思义,通过这个选项指定 Metaspace 空间的最大值。当超过这个值时,将会触发 GC 对该空间进行回收。


CMSClassUnloadingEnable


这个选项的含义是当使用 CMS 算法时,是否进行类卸载(ClassUnloding)。 jdk6 和 jdk7 的默认值都是 false,从 Jdk8 开始默认值变为了 true,也就是默认进行类卸载。


noclassgc


这个选项的含义是不对 class 进行 GC,哪怕这些 class 已经成为垃圾。实际等价于不进行类卸载。现在相当于同时打开了 CMSClassUnloadingEnable 和 noclassgc,那到底类还会不会被卸载呢?


我们来看看 Openjdk 8u40 的源码[1]里对这两个选项的使用(虽然 openjdk 跟 hotspot 的代码有些差别,但大部分逻辑是一样的):


A. globals.hpp L1710


将 CMSClassUnloadingEnabled 默认设置为 true



B. arguments.cppL2786


当指定了-Xnoclassgc 后实际是将 ClassUnloading 设置为 false



C. concurrentMarkSweepGeneration.cppL6262


当需要卸载类时,会去更新类的层次结构(class hierarchy),将卸载的类从对应的链表里删除



D. concurrentMarkSweepGeneration.cpp#update_should_unload_classes


什么时候需要卸载类呢?从这个方法实现可以看到,是否进行类卸载有两个条件, 跟 CMSClassUnloadingEnabled 和 ExplicitGCInvokesConcurrentAndUnloadsClasses 有关,但跟 ClassUnloading 无关



E. kclass.cpp#clean_weak_klass_links


当 ClassUnloading 为 false 时,并不会去更新类的层次结构



原因

所以原因基本上就呼之欲出了,CMS 下,类卸载包含关键的三步:


Unload classes and purge the SystemDictionary.


Unload nmethods.


Prune dead klasses from subklass/sibling/implementor lists.


当 CMSClassUnloadingEnabled 为 true, ClassUnloading 为 false 时, 实际只完成了前两步,而第三步未完成。


也就是说 CMSClassUnloadingEnabled 跟 ClassUnloading 冲突了。


同事那边升级了新版的 jdk 后没有再出现过问题。 我去翻了一下 jdk 的 bugfix list, 发现在 8u60[2]的时候已经 fix 掉了这个 bug[3],修复的方法也很简单[4]:


当 ClassUnloading 为 false 时, 将 CMSClassUnloadingEnabled 和 ExplicitGCInvokesConcurrentAndUnloads 也设置为 false.


启示

  • 保存好故障现场后及时恢复业务、再进行排查分析

  • 不要随便使用自己没掌握的参数选项。

  • 及时升级你 jdk 的小版本,从 bugfix 的 list 也可以看出来,其实 jdk 的 bug 也不 少 :(

  • HotSpot 的启动参数非常之多,实际使用也分散在代码里的各个角落, 几乎没有人能完全搞清楚各个参数之间是否会有冲突, 从易用性上来说,确实比不上 JRocket 和 Zing。


本文转载自公众号贝壳产品技术(ID:gh_9afeb423f390)。


原文链接:


https://mp.weixin.qq.com/s/1h8og5YZstIn2Ii1_enG1A


2019-09-20 14:551047

评论

发布
暂无评论
发现更多内容

优秀工程师必备的一项技能,你解锁了吗?

阿里技术

技术管理 技术人生 内容合集

【浅谈黑客与学习思路】黑客的种类和行为,初学者应该怎样学习

H

黑客 网络安全 信息安全

让“美”势不可挡,DataPipeline助力全球知名化妆品企业数字化营销再提速

DataPipeline数见科技

大数据 中间件 数据融合 数据迁移 数据管理

为什么大部分人做不了架构师?这2点是关键

阿里技术

技术人生 内容合集

7 个建议让 Code Review 高效又高质

阿里技术

技术管理 技术人生 内容合集

第七模块总结

张靖

#架构实战营

高质量的缺陷分析:让自己少写 bug

阿里技术

技术管理 技术人生 内容合集

计算机网络体系结构

淡泊明志、宁静致远

TCP 网络结构

【12月日更】浅谈Golang两种线程安全的map

小梁编程汇

golang 缓存 高性能 并发 多线程安全

关于写文章的一点经验

阿里技术

技术管理 技术人生 内容合集

OPPO大数据离线任务调度系统OFLOW

OPPO数智技术

后端 数据

技术人如何自我成长?

阿里技术

技术管理 技术人生 内容合集

如何优雅的关闭 Java 线程池

淡泊明志、宁静致远

线程池

为企业创建完美CRM系统策略

低代码小观

企业管理 CRM 客户关系管理 CRM系统 客户关系管理系统

如何写好代码?

阿里技术

技术管理 技术人生 内容合集

Python爬虫实战,pymysql模块,Python实现抓取音乐评论

Java全栈架构师

Python MySQL 数据库 程序员 面试

在阿里做了五年技术主管,我有话想说

阿里技术

技术人生 内容合集

Typora + picGo实现插入图片上传gitee图床

zdd

CSS之变量(四)悬浮跟踪按钮

Augus

CSS 12月日更

百度API接口智能化测试探索与实践

百度开发者中心

自动化测试 API测试 智能化测试

揭开神秘面纱,如何组织一次分布式压测

博睿数据

多行内容超出...显示的终极解决方案

CRMEB

Python代码阅读(第71篇):检测一个平坦列表中是否有重复元素

Felix

Python List 编程 阅读代码 Python初学者

EasyRecovery的高级设置如何使用

淋雨

数据恢复 EasyRecovery

一周信创舆情观察(12.13~12.19)

统小信uos

技术三板斧:关于技术规划、管理、架构的思考

阿里技术

技术管理 技术人生 内容合集

面对复杂业务,if-else coder 如何升级?

阿里技术

技术人生 内容合集

谜!JVM为何僵死_文化 & 方法_吴玲_InfoQ精选文章