JDK6u25里添加的按线程统计分配内存量: JMX

2021-02-25 14:54:50 浏览数 (1)

转载自 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:sdkgroovy-1.7.2bin>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. ===> sun.management.ThreadImpl@8b677f  
  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:sdkgroovy-1.7.2bin>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. ===> sun.management.ThreadImpl@9b1670  
  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  

0 人点赞