jvm 性能分析


VM本身提供了一組管理的API,通過該API,我們可以獲取得到JVM內部主要運行信息,包括內存各代的數據、JVM當前所有線程及其棧相關信息等等。各種JDK自帶的剖析工具,包括jps、jstack、jinfo、jstat、jmap、jconsole等,都是基於此API開發的。本篇對這部分內容進行一個詳細的說明。

       參考:http://java.sun.com/javase/6/docs/api/java/lang/management/package-summary.html 
一、Management API
       我們先看一下從Sun JVM我們可以獲取到哪些信息,如下圖(來自於JConsole的MBean部分的截圖):
       
      1.HotSpotDiagnostic:非標准的監控JMX,這塊是Sun JVM自帶的,主要提供了兩個功能

  • 修改JVM的啟動參數(譬如在不需要重啟的情況下設置-XX:+HeapDumpOnOutOfMemoryError參數使得JVM內存不足的時候自動dump出堆空間到文件提供后續分析)
  • Dump堆信息到文件,可以猜測jmap工具是基於此功能來完成的

     我們通過com.sun.management.HotSpotDiagnosticMXBean定義了解其主要功能

Java代碼   收藏代碼
  1. public interface HotSpotDiagnosticMXBean  
  2. {  
  3.     void dumpHeap(String s, boolean flag) throws IOException;  
  4.     List getDiagnosticOptions();  
  5.     VMOption getVMOption(String s);  
  6.     void setVMOption(String s, String s1);  
  7. }  

     2.ClassLoading:加載的類的總體信息,我們可以通過此MBean獲取到JVM加載的類定義的總體信息,可以猜測JConsole的類功能就是通過此MBean來提供的。我們可以通過java.lang.management.ClassLoadingMXBean定義了解其提供的主要功能

Java代碼   收藏代碼
  1. public interface ClassLoadingMXBean {  
  2.     public long getTotalLoadedClassCount();  
  3.     public int getLoadedClassCount();  
  4.     public long getUnloadedClassCount();  
  5.     public boolean isVerbose();  
  6.     public void setVerbose(boolean value);  
  7. }  

     3.Compilation:提供JVM的JIT(Just In Time)編譯器(將bytecode編譯成native code)的信息,我們可以通過java.lang.management.CompilationMXBean定義了解其提供的主要功能

Java代碼   收藏代碼
  1. public interface CompilationMXBean {  
  2.     public java.lang.String    getName();  
  3.     public boolean isCompilationTimeMonitoringSupported();  
  4.     public long                getTotalCompilationTime();  
  5. }  

     4.GarbageCollector:垃圾回收器信息,譬如在如上圖中,我們啟動的JVM會包含一個Copy垃圾回收器(用於Young Gen垃圾回收)和一個MarkAndSweep垃圾回收器(用於Tenured Gen垃圾回收)。我們可以通過java.lang.management.GarbageCollectorMXBean定義了解其提供的主要功能

Java代碼   收藏代碼
  1. public interface GarbageCollectorMXBean extends MemoryManagerMXBean {  
  2.     public long getCollectionCount();  
  3.     public long getCollectionTime();  
  4. }  

    java.lang.management.MemoryManagerMXBean定義是

Java代碼   收藏代碼
  1. public interface MemoryManagerMXBean {  
  2.     public String getName();  
  3.     public boolean isValid();  
  4.     public String[] getMemoryPoolNames();  
  5. }  

    除了如上信息,Sun JVM在實現上還提供了一個額外的信息LastGCInfo,見com.sun.management.GarbageCollectorMXBean定義

Java代碼   收藏代碼
  1. public interface GarbageCollectorMXBean  
  2.     extends java.lang.management.GarbageCollectorMXBean  
  3. {  
  4.     GcInfo getLastGcInfo();  
  5. }  

    我們可以通過下面的截圖了解GcInfo包含的主要信息
    
      其中java.lang.management.MemoryUsage后續可以看說明
      5.內存相關
      可以猜測,JConsole的內存部分的功能都是通過此部分的相關Bean來完成的。
      1)Memory/MemoryManager:內存塊相關信息,通過這MBean我們可以獲取到內存的總體信息,並可以通過提供的gc操作進行強制gc的功能(System.gc())。我們可以通過java.lang.management.MemoryMXBean和java.lang.management.MemoryManagerMXBean了解其主要提供的功能

Java代碼   收藏代碼
  1. public interface MemoryMXBean {  
  2.     public int getObjectPendingFinalizationCount();  
  3.     public MemoryUsage getHeapMemoryUsage();  
  4.     public MemoryUsage getNonHeapMemoryUsage();  
  5.     public boolean isVerbose();  
  6.     public void setVerbose(boolean value);  
  7.     public void gc();  
  8. }  

      其中java.lang.management.MemoryUsage我們可以通過下圖來了解其提供的主要信息

Java代碼   收藏代碼
  1. public interface MemoryManagerMXBean {  
  2.     public String getName();  
  3.     public boolean isValid();  
  4.     public String[] getMemoryPoolNames();  
  5. }  

     2)MemoryPool:通過該MBean可以了解JVM各內存塊的信息,譬如對於Sun JVM,目前包括Eden Space、Suvivor Space、Tenured Gen、CodeCache、Perm Gen,可以猜測JConsole的內存監控功能就是通過此MBean來做到的。我們可以通過java.lang.management.MemoryPoolMXBean了解其主要提供的功能

Java代碼   收藏代碼
  1. public interface MemoryPoolMXBean {  
  2.     public String getName();  
  3.     public MemoryType getType();  
  4.     public MemoryUsage getUsage();  
  5.     public MemoryUsage getPeakUsage();  
  6.     public void resetPeakUsage();  
  7.     public boolean isValid();  
  8.     public String[] getMemoryManagerNames();  
  9.     public long getUsageThreshold();  
  10.     public void setUsageThreshold(long threshold);  
  11.     public boolean isUsageThresholdExceeded();  
  12.     public long getUsageThresholdCount();  
  13.     public boolean isUsageThresholdSupported();  
  14.     public long getCollectionUsageThreshold();  
  15.     public void setCollectionUsageThreshold(long threhsold);  
  16.     public boolean isCollectionUsageThresholdExceeded();  
  17.     public long getCollectionUsageThresholdCount();  
  18.     public MemoryUsage getCollectionUsage();  
  19.     public boolean isCollectionUsageThresholdSupported();  
  20. }  

     6.系統運行信息
     1)OperatingSystem:通過該MBean我們可以了解到JVM所運行在的操作系統上的一些相關信息,通過java.lang.management.OperatingSystemMXBean定義我們可以了解到其主要提供的功能

Java代碼   收藏代碼
  1. public interface OperatingSystemMXBean {  
  2.     public String getName();  
  3.     public String getArch();  
  4.     public String getVersion();  
  5.     public int getAvailableProcessors();  
  6.     public double getSystemLoadAverage();  
  7. }  

      SunJVM在此基礎上提供更多的一些信息,可以通過com.sun.management.OperatingSystemMXBean了解一些額外可以獲取到的信息

Java代碼   收藏代碼
  1. public interface OperatingSystemMXBean  
  2.     extends java.lang.management.OperatingSystemMXBean  
  3. {  
  4.     long getCommittedVirtualMemorySize();  
  5.     long getTotalSwapSpaceSize();  
  6.     long getFreeSwapSpaceSize();  
  7.     long getProcessCpuTime();  
  8.     long getFreePhysicalMemorySize();  
  9.     long getTotalPhysicalMemorySize();  
  10. }  

    2)Runtime:通過該MBean獲取獲取到JVM一些相關的信息,通過java.lang.management.RuntimeMXBean可以了解其主要提供的功能

Java代碼   收藏代碼
  1. public interface RuntimeMXBean {  
  2.     public String getName();  
  3.     public String getVmName();  
  4.     public String getVmVendor();  
  5.     public String getVmVersion();  
  6.     public String getSpecName();  
  7.     public String getSpecVendor();  
  8.     public String getSpecVersion();  
  9.     public String getManagementSpecVersion();  
  10.     public String getClassPath();  
  11.     public String getLibraryPath();  
  12.     public boolean isBootClassPathSupported();  
  13.     public String getBootClassPath();  
  14.     public java.util.List<String> getInputArguments();  
  15.     public long getUptime();  
  16.     public long getStartTime();  
  17.     public java.util.Map<String, String> getSystemProperties();  
  18. }  

      可以通過RuntimeMXBean.getUptime()和OperatingSystemMXBean. getProcessCpuTime()來計算JVM占用的系統CPU比例的情況,JConsole的CPU視圖就是通過這種方式計算的。
      7.Threading:可以通過該MBean獲取線程信息,包括線程狀態、執行棧等。可以通過java.lang.management.ThreadMXBean了解其提供的主要功能

Java代碼   收藏代碼
  1. public interface ThreadMXBean {     
  2.    public int getThreadCount();  
  3.     public int getPeakThreadCount();  
  4.     public long getTotalStartedThreadCount();   
  5.     public int getDaemonThreadCount();  
  6.     public long[] getAllThreadIds();  
  7.     public ThreadInfo getThreadInfo(long id);  
  8.     public ThreadInfo[] getThreadInfo(long[] ids);  
  9.     public ThreadInfo getThreadInfo(long id, int maxDepth);  
  10.     public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth);  
  11.     public boolean isThreadContentionMonitoringSupported();  
  12.     public boolean isThreadContentionMonitoringEnabled();  
  13.     public void setThreadContentionMonitoringEnabled(boolean enable);  
  14.     public long getCurrentThreadCpuTime();  
  15.     public long getCurrentThreadUserTime();  
  16.     public long getThreadCpuTime(long id);  
  17.     public long getThreadUserTime(long id);  
  18.     public boolean isThreadCpuTimeSupported();  
  19.     public boolean isCurrentThreadCpuTimeSupported();  
  20.     public boolean isThreadCpuTimeEnabled();  
  21.     public void setThreadCpuTimeEnabled(boolean enable);  
  22.     public long[] findMonitorDeadlockedThreads();  
  23.     public void resetPeakThreadCount();  
  24.     public long[] findDeadlockedThreads();  
  25.     public boolean isObjectMonitorUsageSupported();  
  26.     public boolean isSynchronizerUsageSupported();  
  27.     public ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers);  
  28.     public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers);  
  29. }  

     二、編程獲取到JVM Manage信息
我們可以通過JMX的方式讀取到JVM Manage定義的MBean,如下是3種獲取方法
     1.監控應用與被監控應用位於同一JVM

Java代碼   收藏代碼
  1. MBeanServer server = ManagementFactory.getPlatformMBeanServer();  
  2. RuntimeMXBean rmxb = ManagementFactory.newPlatformMXBeanProxy(server,  
  3.                 "java.lang:type=Runtime", RuntimeMXBean.class);  

      2.監控應用與被監控應用不位於同一JVM
      1)首先在被監控的JVM的啟動參數中加入如下的啟動參數以啟JVM代理

-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=127.0.0.1:8000 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false

      2)連接到代理上

Java代碼   收藏代碼
  1. JMXServiceURL url = new JMXServiceURL(  
  2.         "service:jmx:rmi:///jndi/rmi://127.0.0.1:8000/jmxrmi");  
  3. JMXConnector connector = JMXConnectorFactory.connect(url);  
  4. RuntimeMXBean rmxb = ManagementFactory.newPlatformMXBeanProxy(connector  
  5.             .getMBeanServerConnection(),"java.lang:type=Runtime",  
  6.                 RuntimeMXBean.class);  

     3.監控應用與被監控應用不位於同一JVM但在同一物理主機上(2的特化情況,通過進程Attach)
       我們使用JDK工具,如jmap、jstack等的時候,工具所在的JVM當然與被監控的JVM不是同一個,所以不能使用方式1,被監控的JVM一般也不會在啟動參數中增加JMX的支持,所以方式2也沒有辦法。還好Sun JVM給我們提供了第3種非標准的方式,就是通過Attach到被監控的JVM進程,並在被監控的JVM中啟動一個JMX代理,然后使用該代理通過2的方式連接到被監控的JVM的JMX上。下面是一個使用范例,由於里面使用到的知識涉及到Java Instrutment(JVMTI的一個技術的Java實現)和Attach API,因此此處不做詳細解析,在后續看完Java Instrutment和Attach API自然就會明白。(注意,僅在JDK6+中支持,另外,運行需要jdk的tools.jar包)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM