1. 程式人生 > >JDK6u25裡新增的按執行緒統計分配記憶體量: JMX

JDK6u25裡新增的按執行緒統計分配記憶體量: JMX

轉載自 http://rednaxelafx.iteye.com/blog/1021619

Oracle幾天前釋出的JDK 6 update 25裡新增的一個新功能非常有趣,可以按照執行緒來跟蹤(GC堆)記憶體的分配量。這個功能在VM核心、直譯器、C1編譯器、C2編譯器以及GC中都有程式碼支援,並且通過JMX API暴露出來。 
不過新加的這功能不是加在java.開頭的包裡,而是加在com.sun.management.ThreadMXBean這個介面上,要用的話還得cast一下。 

當然,這麼底層的功能不可能沒有代價。新增這個功能後,在GC堆上分配空間的slow-path會比以前稍微慢一些。但希望對整體效能的影響並不大吧。 
Fast-path是在TLAB上分配空間的,而TLAB的分配資料是在TLAB refill的時候才批量更新,所以這個功能對fast-path的執行效率基本上沒影響,以稍微放寬資料精準性為代價。 

相關連結: 

Bug ID 7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis 
changeset 

JMX中,該功能由ThreadMXBean上新增的幾個方法提供。詳情可見下面例子。 
ThreadMXBean.getThreadAllocatedBytes(long threadId)的用法基本上可以看成跟System.currentTimeMillis()用於計時的用法一樣,在兩點上記錄並且求差即可。 

不知道為什麼JVMTI沒得到這個更新,或許是因為更新JVMTI spec涉及committee stuff? 

============================================================== 

直接拿一段Groovy指令碼來演示吧: 

先看JDK 6 update 24的情況 

Groovysh程式碼 

 收藏程式碼

  1. D:\sdk\groovy-1.7.2\bin>groovysh  
  2. Groovy Shell (1.7.2, JVM: 1.6.0_24)  
  3. Type 'help' or '\h' for help.  
  4. -------------------------------------------------------------------------------  
  5. groovy:000> import java.lang.management.*  
  6. ===> [import java.lang.management.*]  
  7. groovy:000> tb = ManagementFactory.threadMXBean  
  8. ===> [email protected]  
  9. groovy:000> tb.class.methods.name.unique().sort()  
  10. ===> [dumpAllThreads, equals, findDeadlockedThreads, findMonitorDeadlockedThreads, getAllThreadIds, getClass, getCurrentThreadCpuTime, getCurrentThreadUserTime, getDaemonThreadCount, getPeakThreadCount, getThreadCount, getThreadCpuTime, getThreadInfo, getThreadUserTime, getTotalStartedThreadCount, hashCode, isCurrentThreadCpuTimeSupported, isObjectMonitorUsageSupported, isSynchronizerUsageSupported, isThreadContentionMonitoringEnabled, isThreadContentionMonitoringSupported, isThreadCpuTimeEnabled, isThreadCpuTimeSupported, notify, notifyAll, resetPeakThreadCount, setThreadContentionMonitoringEnabled, setThreadCpuTimeEnabled, toString, wait]  
  11. groovy:000> tb.class.methods.findAll { it.name =~ /Alloc/}.each { println it }; null  
  12. ===> null  


這個時候ThreadMXBean上還沒有跟alloc相關的方法。 
 

Groovysh程式碼 

 收藏程式碼

  1. D:\sdk\groovy-1.7.2\bin>groovysh  
  2. Groovy Shell (1.7.2, JVM: 1.6.0_25)  
  3. Type 'help' or '\h' for help.  
  4. -------------------------------------------------------------------------------  
  5. groovy:000> import java.lang.management.*  
  6. ===> [import java.lang.management.*]  
  7. groovy:000> tb = ManagementFactory.threadMXBean  
  8. ===> [email protected]  
  9. groovy:000> tb.class.methods.name.unique().sort()  
  10. ===> [dumpAllThreads, equals, findDeadlockedThreads, findMonitorDeadlockedThreads, getAllThreadIds, getClass, getCurrentThreadCpuTime, getCurrentThreadUserTime, getDaemonThreadCount, getPeakThreadCount, getThreadAllocatedBytes, getThreadCount, getThreadCpuTime, getThreadInfo, getThreadUserTime, getTotalStartedThreadCount, hashCode, isCurrentThreadCpuTimeSupported, isObjectMonitorUsageSupported, isSynchronizerUsageSupported, isThreadAllocatedMemoryEnabled, isThreadAllocatedMemorySupported, isThreadContentionMonitoringEnabled, isThreadContentionMonitoringSupported, isThreadCpuTimeEnabled, isThreadCpuTimeSupported, notify, notifyAll, resetPeakThreadCount, setThreadAllocatedMemoryEnabled, setThreadContentionMonitoringEnabled, setThreadCpuTimeEnabled, toString, wait]  
  11. groovy:000> tb.class.methods.findAll { it.name =~ /Alloc/}.each { println it };  
  12. null  
  13. public boolean sun.management.ThreadImpl.isThreadAllocatedMemoryEnabled()  
  14. public boolean sun.management.ThreadImpl.isThreadAllocatedMemorySupported()  
  15. public long[] sun.management.ThreadImpl.getThreadAllocatedBytes(long[])  
  16. public long sun.management.ThreadImpl.getThreadAllocatedBytes(long)  
  17. public void sun.management.ThreadImpl.setThreadAllocatedMemoryEnabled(boolean)  
  18. ===> null  
  19. groovy:000> tb.threadAllocatedMemoryEnabled  
  20. ===> true  
  21. groovy:000> tid = Thread.currentThread().id  
  22. ===> 1  
  23. groovy:000> tb.getThreadAllocatedBytes(tid)  
  24. ===> 48106672  
  25. groovy:000> tb.getThreadAllocatedBytes(tid)  
  26. ===> 48751520  
  27. groovy:000> tb.getThreadAllocatedBytes(tid)  
  28. ===> 49384752  
  29. groovy:000> tb.getThreadAllocatedBytes(tid)  
  30. ===> 50086240  
  31. groovy:000> quit