JVM Management API

Posted chuquan.ou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM Management API相关的知识,希望对你有一定的参考价值。

JVM本身提供了一组管理的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. }  
  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. }  
  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. }  
  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. }  
  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. }  
  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. }  
  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. }  
  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. }  
  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. }  
  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. }  
  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. }  
  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. }  
  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. }  
  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);  
  1. MBeanServer server = <span style="BACKGROUND-COLOR: #00ff40; COLOR: black; " id="casearchresult"><strong>ManagementFactory</strong></span>.getPlatformMBeanServer();  
  2. RuntimeMXBean rmxb = <span style="BACKGROUND-COLOR: #00ff40; COLOR: black; " id="casearchresult"><strong>ManagementFactory</strong></span>.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);  
  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 = <span style="BACKGROUND-COLOR: #00ff40; COLOR: black; " id="casearchresult"><strong>ManagementFactory</strong></span>.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包)

Java代码  技术分享技术分享
  1. //Attach 到5656的JVM进程上,后续Attach API再讲解  
  2. VirtualMachine virtualmachine = VirtualMachine.attach("5656");  
  3.   
  4. //让JVM加载jmx Agent,后续讲到Java Instrutment再讲解  
  5. String javaHome = virtualmachine.getSystemProperties().getProperty("java.home");  
  6. String jmxAgent = javaHome + File.separator + "lib" + File.separator + "management-agent.jar";  
  7. virtualmachine.loadAgent(jmxAgent, "com.sun.management.jmxremote");  
  8.   
  9. //获得连接地址  
  10. Properties properties = virtualmachine.getAgentProperties();  
  11. String address = (String)properties.get("com.sun.management.jmxremote.localConnectorAddress");  
  12.          
  13. //Detach  
  14. virtualmachine.detach();  
  15.          
  16. JMXServiceURL url = new JMXServiceURL(address);  
  17. JMXConnector connector = JMXConnectorFactory.connect(url);  
  18. RuntimeMXBean rmxb = ManagementFactory.newPlatformMXBeanProxy(connector  
  19.                 .getMBeanServerConnection(), "java.lang:type=Runtime",RuntimeMXBean.class);  
  1. //Attach 到5656的JVM进程上,后续Attach API再讲解  
  2. VirtualMachine virtualmachine = VirtualMachine.attach("5656");  
  3.   
  4. //让JVM加载jmx Agent,后续讲到Java Instrutment再讲解  
  5. String javaHome = virtualmachine.getSystemProperties().getProperty("java.home");  
  6. String jmxAgent = javaHome + File.separator + "lib" + File.separator + "management-agent.jar";  
  7. virtualmachine.loadAgent(jmxAgent, "com.sun.management.jmxremote");  
  8.   
  9. //获得连接地址  
  10. Properties properties = virtualmachine.getAgentProperties();  
  11. String address = (String)properties.get("com.sun.management.jmxremote.localConnectorAddress");  
  12.          
  13. //Detach  
  14. virtualmachine.detach();  
  15.          
  16. JMXServiceURL url = new JMXServiceURL(ad

以上是关于JVM Management API的主要内容,如果未能解决你的问题,请参考以下文章

查看JVM

使用Java visualVM监控远程JVM

jvm调优

JVM 运行参数 & 代码监控

Java内存使用量测试 看看我们天天在用的JVM到底浪费了多少内存资源

spark streaming 程序设置jvm参数