不起眼,可是足以让你收获的JVM内存案例

今天的这个案例我以为应该会让你涨姿式吧,无论你对JVM有多熟悉,看到这篇文章,应该仍是会有点小惊讶的,不过我以为这个案例我分享出来,是想表达无论多么奇怪的现象请必定要追究下去,会让你慢慢变得强大起来,我对奇怪现象一直充满好奇,因此你碰到些奇怪的问题也能够发给我,固然最好是JVM相关的数组

问题

由于编辑比较麻烦,直接以截图的方式发出来吧image.pngimage.pngimage.png另外附上测试源码:image.png这个问题描述其实还挺详细的,另外还附上了测试代码,我比较喜欢这种提问题的方式,能够简单模拟出问题来,这样也比较好分析,问题简化是很重要的一步,这样能节省不少时间,有些现象甚至都不用描述太多,很快就能抓住点多线程

分析

简化程序

这个问题说白了,就是说有些int[]对象不知道是哪里来的,因而我拿他的例子跑了跑,好像还真有这么回事,因而我不断简化他的代码,最终发现int[]对象的多少和线程run方法里的最后一个byte数组的建立有必定关系。测试

初步疑点

我以为不该该啊,byte数组在内存里明明就是byte数组,和int数组也没半毛钱关系呀,当时忽然灵光一闪,这估计是由于jmx通讯致使的吧,由于jvisualvm和目标进程通讯,传递一些数据也挺正常,由于当时比较忙,因而就回复他了,也许是jmx致使的,要它不要使用visualvm看了,jmx端口也关了,能够经过jmap -histo来确认下。线程

再次怀疑

今天忽然又收到了该同窗的邮件了,他也注意到了和那个byte数组有必定关系image.pngimage.png同时他还发现个现象,也就是我要他确认的方式,发现jmap -histo执行的时候,int数组仍是比较多,可是加了live参数以后,降下去了,降下去这个比较好解释,由于live参数会作一次fgc的动做,把某些死对象给回收掉了3d

再次分析

我因而拿它的demo又跑了跑,按照下面的步骤进行操做cdn

  • 执行jmap -histo,发现int数组比较多
  • 再执行jmap -histo:live,发现int数组降下去了
  • 继续执行jmap -histo,int数组又多了点

执行到这里,我就开始怀疑jmap了,难道是由于jmap致使的?因而我开始check jmap的实现,包括JDK和JVM里的逻辑,我要找到哪里可能会建立int数组,JDK层面基本能够忽略,由于实在想不到会有啥逻辑可能会有int数组产生,只是发了个命令给JVM进程而已,因而我重点分析JVM层面的实现,当咱们使用jmap作了一次dump的时候或者gc发生的时候都会走到下面的逻辑image.png由于GC或者内存dump,都必须对内存作一个遍历,所以必须先暂停这些Java线程,防止在遍历内存里的对象的时候进行内存分配,可是每一个线程分配内存其实都是优先走tlab(每一个线程独有的一块在eden里的小内存块)的,为了能快速遍历对象,而不存在不连续的内存,因而JVM会对tlab作一个填充,填充的正好是int数组对象(从上面代码得知),将剩下的没被分配的tlab内存给填满了,所以在系统运行过程当中其实可能伴随着不少无用的对象产生,哈哈,看到这里你是否是豁然开朗?对象

你是否能够解释以下问题了?blog

  • 线程越多,int数组增加越快
  • 没有分配byte数组,int数组增加很慢,甚至不增加?
  • jmap其实也不是惟一的因素

这个案例仍是很是有意思的,上述问题我抛出来给你们,你们能够到下面留言回答上面的问题,若是没人回答或者没有正确的答案,我到时到下面留言补充,看你们的热情度?欢迎你们转发给更多的人。进程

欢迎关注 PerfMa 社区,推荐阅读:
Java多线程知识小抄集(一)
海量链接服务端CMS调优记内存

相关文章
相关标签/搜索