概述

之所以想写这篇文章,是因为YGC过程对我们来说太过于黑盒,如果对YGC过程不是很熟悉,这类问题基本很难定位,我们就算开了GC日志,也最多能看到类似下面的日志

1
[GC (Allocation Failure) [ParNew: 91807K->10240K(92160K), 0.0538384 secs] 91807K->21262K(2086912K), 0.0538680 secs] [Times: user=0.16 sys=0.06, real=0.06 secs] 

只知道耗了多长时间,但是具体耗在了哪个阶段,是基本看不出来的,所以要么就是靠经验来定位,要么就是对代码相当熟悉,脑袋里过一遍整个过程,看哪个阶段最可能,今天要讲的这个大家可以当做今后排查这类问题的一个经验来使,这个当然不是唯一导致YGC过长的一个原因,但却是最近我帮忙定位碰到的发生相对来说比较多的一个场景

Read on →
jvm

概述

本文要说的内容是今天公司有个线上系统踩了一个坑,并且貌似还造成了一定的影响,后来系统相关的人定位到了是java.lang.Class.getMethods返回的顺序可能不同机器不一样,有问题的机器和没问题的机器这个返回的方法列表是不一样的,后面他们就来找到我求证是否jdk里有这潜规则

本来这个问题简单一句话就可以说明白,所以在晚上推送的消息里也将这个事实告诉了大家,大家知道就好,以后不要再掉到坑里去了,但是这个要细说起来其实也值得一说,于是在消息就附加了征求大家意见的内容,看大家是否有兴趣或者是否踩到过此坑,没想到有这么多人响应,表示对这个话题很感兴趣,并且总结了大家问得最多的两个问题是

  • 为什么有代码需要依赖这个顺序
  • jvm里为什么不保证顺序

那这篇文章主要就针对这两个问题展开说一下,另外以后针对此类可写可不写的文章先征求下大家的意见再来写可能效果会更好点,一来可以回答大家的一些疑问(当然有些问题我也可能回答不上来,不过我尽量去通读代码回答好大家),二来希望对我公众号里的文章继续保持不求最多,只求最精的态度。

为了不辜负大家的热情,我连夜赶写了这篇文章,如果大家觉得我写的这些文章对大家有帮助,希望您能将文章分享出去,同时将我的公众号你假笨推荐给您身边更多的技术人,能帮助到更多的人去了解更多的细节,在下在此先谢过。

Read on →

概述

metaspace,顾名思义,元数据空间,专门用来存元数据的,它是jdk8里特有的数据结构用来替代perm,这块空间很有自己的特点,前段时间公司这块的问题太多了,主要是因为升级了中间件所致,看到大家讨论来讨论去,看得出很多人对metaspace还是模棱两可,不是很了解它,因此我觉得有必要写篇文章来介绍一下它,解开它神秘的面纱,当我们再次碰到它的相关问题的时候不会再感到束手无策。

通过这篇文章,你将可以了解到

  • 为什么会有metaspace
  • metaspace的组成
  • metaspace的VM参数
  • jstat里我们应该关注metaspace的哪些值
Read on →
jvm, oom

概述

OutOfMemoryError,说的是java.lang.OutOfMemoryError,是JDK里自带的异常,顾名思义,说的就是内存溢出,当我们的系统内存严重不足的时候就会抛出这个异常(PS:注意这是一个Error,不是一个Exception,所以当我们要catch异常的时候要注意哦),这个异常说常见也常见,说不常见其实也见得不多,不过作为Java程序员至少应该都听过吧,如果你对jvm不是很熟,或者对OutOfMemoryError这个异常了解不是很深的话,这篇文章肯定还是可以给你带来一些惊喜的,通过这篇文章你至少可以了解到如下几点:

  • OutOfMemoryError一定会被加载吗
  • 什么时候抛出OutOfMemoryError
  • 会创建无数OutOfMemoryError实例吗
  • 为什么大部分OutOfMemoryError异常是无堆栈的
  • 我们如何去分析这样的异常
Read on →

概述

jstat是hotspot自带的工具,和java一样也位于JAVA_HOME/bin下面,我们通过该工具可以实时了解当前进程的gc,compiler,class,memory等相关的情况,具体我们可以通过jstat -options来看我们到底支持哪些类型的数据,譬如JDK8下的结果是:

1
2
3
4
5
6
7
8
9
10
11
12
-class
-compiler
-gc
-gccapacity
-gccause
-gcmetacapacity
-gcnew
-gcnewcapacity
-gcold
-gcoldcapacity
-gcutil
-printcompilation
Read on →

概述

之前写过篇文章,关于堆外内存的,JVM源码分析之堆外内存完全解读,里面重点讲了DirectByteBuffer的原理,但是今天碰到一个比较奇怪的问题,在设置了-XX:MaxDirectMemorySize=1G的前提下,然后统计所有DirectByteBuffer对象后面占用的内存达到了7G,远远超出阈值,这个问题很诡异,于是好好查了下原因,虽然最终发现是我们统计的问题,但是期间发现的其他一些问题还是值得分享一下的。

Read on →
gc, jvm

问题描述

我们都知道gc是为了释放内存,但是你是否碰到过ygc前后新生代反增不减的情况呢?gc日志效果类似下面的:

1
2016-05-18T15:06:13.011+0800: [GC [ParNew (promotion failed): 636088K->690555K(707840K), 0.2958900 secs][CMS: 1019739K->1019733K(1310720K), 2.6208600 secs] 1655820K->1655820K(2018560K), [CMS Perm : 205486K->205486K(262144K)], 2.9174390 secs] [Times: user=3.74 sys=0.01, real=2.91 secs]

从上面的gc日志来看,我们新生代使用的是ParNew,而老生代用的是CMS GC,我们注意到ParNew的效果是新生代从636088K新增到了690555K,这是什么情况?

Read on →

概述

这篇文章基于最近在排查的一个问题,花了我们团队不少时间来排查这个问题,现象是有一些类加载器是作为key放到WeakHashMap里的,但是经历过多次full gc之后,依然坚挺地存在内存里,但是从代码上来说这些类加载器是应该被回收的,因为没有任何强引用可以到达这些类加载器了,于是我们做了内存dump,分析了下内存,发现除了一个WeakHashMap外并没有别的GC ROOT途径达到这些类加载器了,那这样一来经过多次FULL GC肯定是可以被回收的,但是事实却不是这样,为了让这个问题听起来更好理解,还是照例先上个Demo,完全模拟了这种场景。

Read on →

概述

之所以想写这篇文章,其实是因为最近有不少系统出现了栈溢出导致进程crash的问题,并且很隐蔽,根本原因还得借助coredump才能分析出来,于是想从JVM实现的角度来全面分析下栈溢出的这类问题,或许你碰到过如下的场景:

  • 日志里出现了StackOverflowError的异常
  • 进程突然消失了,但是留下了crash日志
  • 进程消失了,crash日志也没有留下

这些都可能是栈溢出导致的。

Read on →

概述

最近公司在大面积推广JDK8,整体来说升级上来算顺利的,大部分问题可能在编译期就碰到了,但是有些时候比较蛋疼,编译期没有出现问题,但是在运行期就出了问题,比如今天要说的这个话题,所以大家再升级的时候还是要多测测再上线,当然JDK8给我们带来了不少收益,花点时间升级上来还是值得的。

Read on →