jvm内存 大于 xmx_为什么我的JVM访问的内存少于通过-Xmx指定的内存?
jvm內(nèi)存 大于 xmx
“嘿,你能來看看奇怪的東西嗎?” 這就是我開始研究支持案例的方式,將我引向了這篇博客文章。 眼前的具體問題與報(bào)告可用內(nèi)存數(shù)量不同的不同工具有關(guān)。
簡(jiǎn)而言之,一位工程師正在研究特定應(yīng)用程序的過多內(nèi)存使用情況,據(jù)他所知,該應(yīng)用程序可以使用2G的堆。 但是無論出于什么原因,JVM工具本身似乎都沒有決定該進(jìn)程真正擁有多少內(nèi)存。 例如, jconsole猜測(cè)總可用堆等于1,963M,而jvisualvm聲稱其等于2,048M。 那么哪個(gè)工具是正確的,為什么另一個(gè)卻顯示不同的信息呢?
確實(shí)確實(shí)很奇怪,尤其是看到通常的可疑對(duì)象都被淘汰了– JVM并沒有采取任何明顯的技巧,例如:
- -Xmx和-Xms相等,因此在運(yùn)行時(shí)堆增加期間報(bào)告的數(shù)字不會(huì)更改
- 通過關(guān)閉自適應(yīng)大小調(diào)整策略( -XX:-UseAdaptiveSizePolicy ),防止JVM動(dòng)態(tài)調(diào)整內(nèi)存池的大小
重現(xiàn)差異
理解問題的第一步是放大工具實(shí)現(xiàn)。 通過標(biāo)準(zhǔn)API訪問可用的內(nèi)存信息非常簡(jiǎn)單,如下所示:
System.out.println("Runtime.getRuntime().maxMemory()="+Runtime.getRuntime().maxMemory());確實(shí),這就是手頭工具似乎正在使用的工具。 回答此類問題的第一步是擁有可重現(xiàn)的測(cè)試用例。 為此,我編寫了以下代碼段:
package eu.plumbr.test; //imports skipped for brevitypublic class HeapSizeDifferences {static Collection<Object> objects = new ArrayList<Object>();static long lastMaxMemory = 0;public static void main(String[] args) {try {List<String> inputArguments = ManagementFactory.getRuntimeMXBean().getInputArguments();System.out.println("Running with: " + inputArguments);while (true) {printMaxMemory();consumeSpace();}} catch (OutOfMemoryError e) {freeSpace();printMaxMemory();}}static void printMaxMemory() {long currentMaxMemory = Runtime.getRuntime().maxMemory();if (currentMaxMemory != lastMaxMemory) {lastMaxMemory = currentMaxMemory;System.out.format("Runtime.getRuntime().maxMemory(): %,dK.%n", currentMaxMemory / 1024);}}static void consumeSpace() {objects.add(new int[1_000_000]);}static void freeSpace() {objects.clear();} }該代碼通過循環(huán)中的新int [1_000_000]分配內(nèi)存塊,并檢查當(dāng)前已知可用于JVM運(yùn)行時(shí)的內(nèi)存。 每當(dāng)發(fā)現(xiàn)最后一個(gè)已知的內(nèi)存大小發(fā)生變化時(shí),它都會(huì)通過打印Runtime.getRuntime()。maxMemory()的輸出來報(bào)告該變化,類似于以下內(nèi)容:
Running with: [-Xms2048M, -Xmx2048M] Runtime.getRuntime().maxMemory(): 2,010,112K.確實(shí)- 即使我已指定JVM使用2G堆,運(yùn)行時(shí)也無法以某種方式找到其中的85M 。 您可以通過將Runtime.getRuntime()。maxMemory()的輸出轉(zhuǎn)換為MB(用2,010,112K除以1024 )來仔細(xì)檢查我的數(shù)學(xué)運(yùn)算。結(jié)果將等于1,963M,與2048M相差85M。
尋找根本原因
在能夠重現(xiàn)案例之后,我記下了以下筆記–使用不同的GC算法運(yùn)行似乎也會(huì)產(chǎn)生不同的結(jié)果:
| -XX:+ UseSerialGC | 2,027,264千 |
| -XX:+ UseParallelGC | 2,010,112千 |
| -XX:+ UseConcMarkSweepGC | 2,063,104千 |
| -XX:+ UseG1GC | 2,097,152千 |
除了G1完全消耗了我給該進(jìn)程分配的2G內(nèi)存外,其他所有GC算法似乎都始終丟失半隨機(jī)的內(nèi)存。
現(xiàn)在是時(shí)候深入研究JVM 的源代碼了,在CollectedHeap的源代碼中,我發(fā)現(xiàn)了以下內(nèi)容:
// Support for java.lang.Runtime.maxMemory(): return the maximum amount of // memory that the vm could make available for storing 'normal' java objects. // This is based on the reserved address space, but should not include space // that the vm uses internally for bookkeeping or temporary storage // (e.g., in the case of the young gen, one of the survivor // spaces). virtual size_t max_capacity() const = 0;我不得不承認(rèn)答案是非常隱蔽的。 但是,仍然有一些真正的好奇心可以找到的提示–指的是在某些情況下,堆大小計(jì)算中可能會(huì)排除一個(gè)幸存空間 。
從這里一直是順風(fēng)順?biāo)C打開GC日志記錄發(fā)現(xiàn),實(shí)際上,使用2G堆,串行,并行和CMS算法都將幸存空間的大小恰好設(shè)置為缺少的差值。 例如,在上面的ParallelGC示例中,GC日志記錄演示了以下內(nèi)容:
Running with: [-Xms2g, -Xmx2g, -XX:+UseParallelGC, -XX:+PrintGCDetails] Runtime.getRuntime().maxMemory(): 2,010,112K.... rest of the GC log skipped for brevity ...PSYoungGen total 611840K, used 524800K [0x0000000795580000, 0x00000007c0000000, 0x00000007c0000000)eden space 524800K, 100% used [0x0000000795580000,0x00000007b5600000,0x00000007b5600000)from space 87040K, 0% used [0x00000007bab00000,0x00000007bab00000,0x00000007c0000000)to space 87040K, 0% used [0x00000007b5600000,0x00000007b5600000,0x00000007bab00000)ParOldGen total 1398272K, used 1394966K [0x0000000740000000, 0x0000000795580000, 0x0000000795580000)從中您可以看到Eden空間設(shè)置為524,800K,兩個(gè)幸存者空間(從和到)都設(shè)置為87,040K,舊空間的大小為1,398,272K。 將Eden,Old和一個(gè)幸存者空間加在一起總計(jì)為2,010,112K,這證實(shí)丟失的85M或87,040K確實(shí)是剩余的幸存者空間 。
摘要
閱讀該文章后,您現(xiàn)在對(duì)Java API實(shí)現(xiàn)細(xì)節(jié)有了新的認(rèn)識(shí)。 下次某些工具將總可用堆大小可視化為略小于Xmx指定的堆大小時(shí),您會(huì)知道差值等于其中一個(gè)Survivor空間的大小。
我必須承認(rèn),這一事實(shí)在日常編程活動(dòng)中并不是特別有用,但這不是該帖子的重點(diǎn)。 取而代之的是,我寫了一篇文章,描述了我一直在優(yōu)秀工程師中尋找的一個(gè)特殊特性- 好奇心 。 優(yōu)秀的工程師一直在尋找理解某件事如何以及為什么以它的方式起作用的方法。 有時(shí)答案仍然是隱藏的,但我仍然建議您嘗試尋求答案。 最終,沿途積累的知識(shí)將開始帶來紅利。
翻譯自: https://www.javacodegeeks.com/2015/02/jvm-access-less-memory-specified-via-xmx.html
jvm內(nèi)存 大于 xmx
總結(jié)
以上是生活随笔為你收集整理的jvm内存 大于 xmx_为什么我的JVM访问的内存少于通过-Xmx指定的内存?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三星s10跟s10plus区别是什么
- 下一篇: 1.0jpa 2.0_JPA 2.1:不