2015-07-10 193 views
2

我具有由JavaSpecialists newsletter 調用出到類這種方法threadAllocatedBytes()ManagementFactory爲什麼getThreadAllocatedBytes不一致?

import java.lang.management.ManagementFactory; 
import java.util.Arrays; 

import javax.management.ObjectName; 

public class MemoryTest { 

    public static void main(String[] args) { 
     for (int i = 0; i < 10; ++i) 
      testMemory(i); 
    } 

    private static void testMemory(int nChars) { 
     long bytes = threadAllocatedBytes(); 
     char[] test = new char[nChars]; 
     long bytes2 = threadAllocatedBytes(); 
     System.out.println("diff[" + +(nChars + 1) + "] = " + (bytes2 - bytes)); 
    } 

    public static long threadAllocatedBytes() { 
     try { 
      return (Long) ManagementFactory.getPlatformMBeanServer().invoke(
        new ObjectName(ManagementFactory.THREAD_MXBEAN_NAME), "getThreadAllocatedBytes", 
        new Object[] { Thread.currentThread().getId() }, new String[] { long.class.getName() }); 
     } catch (Exception e) { 
      throw new IllegalArgumentException(e); 
     } 
    } 

該程序的輸出是;

diff[1] = 1072 
diff[2] = 1080 
diff[3] = 1080 
diff[4] = 1080 
diff[5] = 1080 
diff[6] = 1088 
diff[7] = 1088 
diff[8] = 28584 
diff[9] = 1088 
diff[10] = 1096 

爲什麼第8次運行會顯示更高的分配? 我能做些什麼才能使它更加一致?

+0

Interstingly如果測試運行具有不同尺寸的'炭[] test'例如'new char [nChars * 10]',...,'new char [nChars * 1000]',我堅持觀察到大約26-28kb的第8個分配的跳轉,與分配的內存無關。 – wero

回答

1

從文檔

長getThreadAllocatedBytes(長ID)

返回的存儲器總量的近似,以字節爲單位,在 堆內存分配用於指定ID的線程。

+0

我並沒有抱怨它不是非常準確 - 我試圖理解它是關於第8次跑的行爲,這是非常異常的。我們如何處理它? – anjanb

+0

我沒有建議你在抱怨準確性。我向您展示了Sun/Oracle表示不用擔心的部分手冊。爲了進一步瞭解發生了什麼,你必須深入到虛擬機中去理解垃圾收集器以及虛擬機如何在虛擬機上使用它。不要忘記gc是懶惰的,所以儘管你的線程可能已經釋放了一個對象,但gc並沒有將它清理乾淨。 –

0

這是最有可能是由於TLABs被使用。改善性能分配是在一個線程本地分配緩衝區中完成的。這允許分配速度非常快,只需將線程本地指針作爲預留內存的一部分,直到TLAB已滿爲止。

爲了保持良好的性能,當對象在TLAB適合,而內存遞增爲的TLAB退役部分沒有配置跟蹤完成。

if (retire) { 
    myThread()->incr_allocated_bytes(used_bytes()); 
} 

因此,最有可能你使用TLAB作爲8次迭代的一部分,因此看到一個巨大的顛簸。