不起眼,可是足以讓你收穫的JVM內存案例

今天的這個案例我以爲應該會讓你漲姿式吧,無論你對JVM有多熟悉,看到這篇文章,應該仍是會有點小驚訝的,不過我以爲這個案例我分享出來,是想表達無論多麼奇怪的現象請必定要追究下去,會讓你慢慢變得強大起來,我對奇怪現象一直充滿好奇,因此你碰到些奇怪的問題也能夠發給我,固然最好是JVM相關的segmentfault

問題

由於編輯比較麻煩,直接以截圖的方式發出來吧
image.png
image.png
image.png
另外附上測試源碼:
image.png
這個問題描述其實還挺詳細的,另外還附上了測試代碼,我比較喜歡這種提問題的方式,能夠簡單模擬出問題來,這樣也比較好分析,問題簡化是很重要的一步,這樣能節省不少時間,有些現象甚至都不用描述太多,很快就能抓住點數組

分析

簡化程序

這個問題說白了,就是說有些int[]對象不知道是哪裏來的,因而我拿他的例子跑了跑,好像還真有這麼回事,因而我不斷簡化他的代碼,最終發現int[]對象的多少和線程run方法裏的最後一個byte數組的建立有必定關係。多線程

初步疑點

我以爲不該該啊,byte數組在內存裏明明就是byte數組,和int數組也沒半毛錢關係呀,當時忽然靈光一閃,這估計是由於jmx通訊致使的吧,由於jvisualvm和目標進程通訊,傳遞一些數據也挺正常,由於當時比較忙,因而就回復他了,也許是jmx致使的,要它不要使用visualvm看了,jmx端口也關了,能夠經過jmap -histo來確認下。測試

再次懷疑

今天忽然又收到了該同窗的郵件了,他也注意到了和那個byte數組有必定關係
image.png
image.png
同時他還發現個現象,也就是我要他確認的方式,發現jmap -histo執行的時候,int數組仍是比較多,可是加了live參數以後,降下去了,降下去這個比較好解釋,由於live參數會作一次fgc的動做,把某些死對象給回收掉了spa

再次分析

我因而拿它的demo又跑了跑,按照下面的步驟進行操做線程

  • 執行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調優記
相關文章
相關標籤/搜索