JVM自己提供了一组管理的API,经过该API,咱们能够获取获得JVM内部主要运行信息,包括内存各代的数据、JVM当前全部线程及其栈相关信 息等等。各类JDK自带的剖析工具,包括jps、jstack、jinfo、jstat、jmap、jconsole等,都是基于此API开发的。本篇对 这部份内容进行一个详细的说明。html
参考:http://java.sun.com/javase/6/docs/api/java/lang/management/package-summary.html
1、Management API
咱们先看一下从Sun JVM咱们能够获取到哪些信息,以下图(来自于JConsole的MBean部分的截图):

1.HotSpotDiagnostic:非标准的监控JMX,这块是Sun JVM自带的,主要提供了两个功能java
- 修改JVM的启动参数(譬如在不须要重启的状况下设置-XX:+HeapDumpOnOutOfMemoryError参数使得JVM内存不足的时候自动dump出堆空间到文件提供后续分析)
- Dump堆信息到文件,能够猜想jmap工具是基于此功能来完成的
咱们经过com.sun.management.HotSpotDiagnosticMXBean定义了解其主要功能
编程
- public interface HotSpotDiagnosticMXBean
- {
- void dumpHeap(String s, boolean flag) throws IOException;
- List getDiagnosticOptions();
- VMOption getVMOption(String s);
- void setVMOption(String s, String s1);
- }
- public interface HotSpotDiagnosticMXBean
- {
- void dumpHeap(String s, boolean flag) throws IOException;
- List getDiagnosticOptions();
- VMOption getVMOption(String s);
- void setVMOption(String s, String s1);
- }
2.ClassLoading:加载的类的整体信息,咱们能够经过此MBean获取到JVM加载的类定义的整体信息,能够猜想JConsole的类功能就 是经过此MBean来提供的。咱们能够经过java.lang.management.ClassLoadingMXBean定义了解其提供的主要功能api
- public interface ClassLoadingMXBean {
- public long getTotalLoadedClassCount();
- public int getLoadedClassCount();
- public long getUnloadedClassCount();
- public boolean isVerbose();
- public void setVerbose(boolean value);
- }
- public interface ClassLoadingMXBean {
- public long getTotalLoadedClassCount();
- public int getLoadedClassCount();
- public long getUnloadedClassCount();
- public boolean isVerbose();
- public void setVerbose(boolean value);
- }
3.Compilation:提供JVM的JIT(Just In Time)编译器(将bytecode编译成native code)的信息,咱们能够经过java.lang.management.CompilationMXBean定义了解其提供的主要功能架构
- public interface CompilationMXBean {
- public java.lang.String getName();
- public boolean isCompilationTimeMonitoringSupported();
- public long getTotalCompilationTime();
- }
- public interface CompilationMXBean {
- public java.lang.String getName();
- public boolean isCompilationTimeMonitoringSupported();
- public long getTotalCompilationTime();
- }
4.GarbageCollector:垃圾回收器信息,譬如在如上图中,咱们启动的JVM会包含一个Copy垃圾回收器(用于Young Gen垃圾回收)和一个MarkAndSweep垃圾回收器(用于Tenured Gen垃圾回收)。咱们能够经过java.lang.management.GarbageCollectorMXBean定义了解其提供的主要功能工具
- public interface GarbageCollectorMXBean extends MemoryManagerMXBean {
- public long getCollectionCount();
- public long getCollectionTime();
- }
- public interface GarbageCollectorMXBean extends MemoryManagerMXBean {
- public long getCollectionCount();
- public long getCollectionTime();
- }
java.lang.management.MemoryManagerMXBean定义是性能
- public interface MemoryManagerMXBean {
- public String getName();
- public boolean isValid();
- public String[] getMemoryPoolNames();
- }
- public interface MemoryManagerMXBean {
- public String getName();
- public boolean isValid();
- public String[] getMemoryPoolNames();
- }
除了如上信息,Sun JVM在实现上还提供了一个额外的信息LastGCInfo,见com.sun.management.GarbageCollectorMXBean定义fetch
- public interface GarbageCollectorMXBean
- extends java.lang.management.GarbageCollectorMXBean
- {
- GcInfo getLastGcInfo();
- }
- public interface GarbageCollectorMXBean
- extends java.lang.management.GarbageCollectorMXBean
- {
- GcInfo getLastGcInfo();
- }
咱们能够经过下面的截图了解GcInfo包含的主要信息

其中java.lang.management.MemoryUsage后续能够看说明
5.内存相关
能够猜想,JConsole的内存部分的功能都是经过此部分的相关Bean来完成的。
1)Memory/MemoryManager:内存块相关信息,经过这MBean咱们能够获取到内存的整体信息,并能够经过提供的gc操做进行强制gc 的功能(System.gc())。咱们能够经过java.lang.management.MemoryMXBean和 java.lang.management.MemoryManagerMXBean了解其主要提供的功能url
- public interface MemoryMXBean {
- public int getObjectPendingFinalizationCount();
- public MemoryUsage getHeapMemoryUsage();
- public MemoryUsage getNonHeapMemoryUsage();
- public boolean isVerbose();
- public void setVerbose(boolean value);
- public void gc();
- }
- public interface MemoryMXBean {
- public int getObjectPendingFinalizationCount();
- public MemoryUsage getHeapMemoryUsage();
- public MemoryUsage getNonHeapMemoryUsage();
- public boolean isVerbose();
- public void setVerbose(boolean value);
- public void gc();
- }
其中java.lang.management.MemoryUsage咱们能够经过下图来了解其提供的主要信息spa

- public interface MemoryManagerMXBean {
- public String getName();
- public boolean isValid();
- public String[] getMemoryPoolNames();
- }
- public interface MemoryManagerMXBean {
- public String getName();
- public boolean isValid();
- public String[] getMemoryPoolNames();
- }
2)MemoryPool:经过该MBean能够了解JVM各内存块的信息,譬如对于Sun JVM,目前包括Eden Space、Suvivor Space、Tenured Gen、CodeCache、Perm Gen,能够猜想JConsole的内存监控功能就是经过此MBean来作到的。咱们能够经过 java.lang.management.MemoryPoolMXBean了解其主要提供的功能
- public interface MemoryPoolMXBean {
- public String getName();
- public MemoryType getType();
- public MemoryUsage getUsage();
- public MemoryUsage getPeakUsage();
- public void resetPeakUsage();
- public boolean isValid();
- public String[] getMemoryManagerNames();
- public long getUsageThreshold();
- public void setUsageThreshold(long threshold);
- public boolean isUsageThresholdExceeded();
- public long getUsageThresholdCount();
- public boolean isUsageThresholdSupported();
- public long getCollectionUsageThreshold();
- public void setCollectionUsageThreshold(long threhsold);
- public boolean isCollectionUsageThresholdExceeded();
- public long getCollectionUsageThresholdCount();
- public MemoryUsage getCollectionUsage();
- public boolean isCollectionUsageThresholdSupported();
- }
- public interface MemoryPoolMXBean {
- public String getName();
- public MemoryType getType();
- public MemoryUsage getUsage();
- public MemoryUsage getPeakUsage();
- public void resetPeakUsage();
- public boolean isValid();
- public String[] getMemoryManagerNames();
- public long getUsageThreshold();
- public void setUsageThreshold(long threshold);
- public boolean isUsageThresholdExceeded();
- public long getUsageThresholdCount();
- public boolean isUsageThresholdSupported();
- public long getCollectionUsageThreshold();
- public void setCollectionUsageThreshold(long threhsold);
- public boolean isCollectionUsageThresholdExceeded();
- public long getCollectionUsageThresholdCount();
- public MemoryUsage getCollectionUsage();
- public boolean isCollectionUsageThresholdSupported();
- }
6.系统运行信息
1)OperatingSystem:经过该MBean咱们能够了解到JVM所运行在的操做系统上的一些相关信息,经过java.lang.management.OperatingSystemMXBean定义咱们能够了解到其主要提供的功能
- public interface OperatingSystemMXBean {
- public String getName();
- public String getArch();
- public String getVersion();
- public int getAvailableProcessors();
- public double getSystemLoadAverage();
- }
- public interface OperatingSystemMXBean {
- public String getName();
- public String getArch();
- public String getVersion();
- public int getAvailableProcessors();
- public double getSystemLoadAverage();
- }
SunJVM在此基础上提供更多的一些信息,能够经过com.sun.management.OperatingSystemMXBean了解一些额外能够获取到的信息
- public interface OperatingSystemMXBean
- extends java.lang.management.OperatingSystemMXBean
- {
- long getCommittedVirtualMemorySize();
- long getTotalSwapSpaceSize();
- long getFreeSwapSpaceSize();
- long getProcessCpuTime();
- long getFreePhysicalMemorySize();
- long getTotalPhysicalMemorySize();
- }
- public interface OperatingSystemMXBean
- extends java.lang.management.OperatingSystemMXBean
- {
- long getCommittedVirtualMemorySize();
- long getTotalSwapSpaceSize();
- long getFreeSwapSpaceSize();
- long getProcessCpuTime();
- long getFreePhysicalMemorySize();
- long getTotalPhysicalMemorySize();
- }
2)Runtime:经过该MBean获取获取到JVM一些相关的信息,经过java.lang.management.RuntimeMXBean能够了解其主要提供的功能
- public interface RuntimeMXBean {
- public String getName();
- public String getVmName();
- public String getVmVendor();
- public String getVmVersion();
- public String getSpecName();
- public String getSpecVendor();
- public String getSpecVersion();
- public String getManagementSpecVersion();
- public String getClassPath();
- public String getLibraryPath();
- public boolean isBootClassPathSupported();
- public String getBootClassPath();
- public java.util.List<String> getInputArguments();
- public long getUptime();
- public long getStartTime();
- public java.util.Map<String, String> getSystemProperties();
- }
- public interface RuntimeMXBean {
- public String getName();
- public String getVmName();
- public String getVmVendor();
- public String getVmVersion();
- public String getSpecName();
- public String getSpecVendor();
- public String getSpecVersion();
- public String getManagementSpecVersion();
- public String getClassPath();
- public String getLibraryPath();
- public boolean isBootClassPathSupported();
- public String getBootClassPath();
- public java.util.List<String> getInputArguments();
- public long getUptime();
- public long getStartTime();
- public java.util.Map<String, String> getSystemProperties();
- }
能够经过RuntimeMXBean.getUptime()和OperatingSystemMXBean. getProcessCpuTime()来计算JVM占用的系统CPU比例的状况,JConsole的CPU视图就是经过这种方式计算的。
7.Threading:能够经过该MBean获取线程信息,包括线程状态、执行栈等。能够经过java.lang.management.ThreadMXBean了解其提供的主要功能
- public interface ThreadMXBean {
- public int getThreadCount();
- public int getPeakThreadCount();
- public long getTotalStartedThreadCount();
- public int getDaemonThreadCount();
- public long[] getAllThreadIds();
- public ThreadInfo getThreadInfo(long id);
- public ThreadInfo[] getThreadInfo(long[] ids);
- public ThreadInfo getThreadInfo(long id, int maxDepth);
- public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth);
- public boolean isThreadContentionMonitoringSupported();
- public boolean isThreadContentionMonitoringEnabled();
- public void setThreadContentionMonitoringEnabled(boolean enable);
- public long getCurrentThreadCpuTime();
- public long getCurrentThreadUserTime();
- public long getThreadCpuTime(long id);
- public long getThreadUserTime(long id);
- public boolean isThreadCpuTimeSupported();
- public boolean isCurrentThreadCpuTimeSupported();
- public boolean isThreadCpuTimeEnabled();
- public void setThreadCpuTimeEnabled(boolean enable);
- public long[] findMonitorDeadlockedThreads();
- public void resetPeakThreadCount();
- public long[] findDeadlockedThreads();
- public boolean isObjectMonitorUsageSupported();
- public boolean isSynchronizerUsageSupported();
- public ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers);
- public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers);
- }
- public interface ThreadMXBean {
- public int getThreadCount();
- public int getPeakThreadCount();
- public long getTotalStartedThreadCount();
- public int getDaemonThreadCount();
- public long[] getAllThreadIds();
- public ThreadInfo getThreadInfo(long id);
- public ThreadInfo[] getThreadInfo(long[] ids);
- public ThreadInfo getThreadInfo(long id, int maxDepth);
- public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth);
- public boolean isThreadContentionMonitoringSupported();
- public boolean isThreadContentionMonitoringEnabled();
- public void setThreadContentionMonitoringEnabled(boolean enable);
- public long getCurrentThreadCpuTime();
- public long getCurrentThreadUserTime();
- public long getThreadCpuTime(long id);
- public long getThreadUserTime(long id);
- public boolean isThreadCpuTimeSupported();
- public boolean isCurrentThreadCpuTimeSupported();
- public boolean isThreadCpuTimeEnabled();
- public void setThreadCpuTimeEnabled(boolean enable);
- public long[] findMonitorDeadlockedThreads();
- public void resetPeakThreadCount();
- public long[] findDeadlockedThreads();
- public boolean isObjectMonitorUsageSupported();
- public boolean isSynchronizerUsageSupported();
- public ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers);
- public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers);
- }
2、编程获取到JVM Manage信息
咱们能够经过JMX的方式读取到JVM Manage定义的MBean,以下是3种获取方法
1.监控应用与被监控应用位于同一JVM
- MBeanServer server = ManagementFactory.getPlatformMBeanServer();
- RuntimeMXBean rmxb = ManagementFactory.newPlatformMXBeanProxy(server,
- "java.lang:type=Runtime", RuntimeMXBean.class);
- MBeanServer server = <span style="BACKGROUND-COLOR: #00ff40; COLOR: black; " id="casearchresult"><strong>ManagementFactory</strong></span>.getPlatformMBeanServer();
- RuntimeMXBean rmxb = <span style="BACKGROUND-COLOR: #00ff40; COLOR: black; " id="casearchresult"><strong>ManagementFactory</strong></span>.newPlatformMXBeanProxy(server,
- "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)链接到代理上
- JMXServiceURL url = new JMXServiceURL(
- "service:jmx:rmi:///jndi/rmi://127.0.0.1:8000/jmxrmi");
- JMXConnector connector = JMXConnectorFactory.connect(url);
- RuntimeMXBean rmxb = ManagementFactory.newPlatformMXBeanProxy(connector
- .getMBeanServerConnection(),"java.lang:type=Runtime",
- RuntimeMXBean.class);
- JMXServiceURL url = new JMXServiceURL(
- "service:jmx:rmi:///jndi/rmi://127.0.0.1:8000/jmxrmi");
- JMXConnector connector = JMXConnectorFactory.connect(url);
- RuntimeMXBean rmxb = <span style="BACKGROUND-COLOR: #00ff40; COLOR: black; " id="casearchresult"><strong>ManagementFactory</strong></span>.newPlatformMXBeanProxy(connector
- .getMBeanServerConnection(),"java.lang:type=Runtime",
- 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包)
- VirtualMachine virtualmachine = VirtualMachine.attach("5656");
-
- String javaHome = virtualmachine.getSystemProperties().getProperty("java.home");
- String jmxAgent = javaHome + File.separator + "lib" + File.separator + "management-agent.jar";
- virtualmachine.loadAgent(jmxAgent, "com.sun.management.jmxremote");
-
- Properties properties = virtualmachine.getAgentProperties();
- String address = (String)properties.get("com.sun.management.jmxremote.localConnectorAddress");
-
- virtualmachine.detach();
-
- JMXServiceURL url = new JMXServiceURL(address);
- JMXConnector connector = JMXConnectorFactory.connect(url);
- RuntimeMXBean rmxb = ManagementFactory.newPlatformMXBeanProxy(connector
- .getMBeanServerConnection(), "java.lang:type=Runtime",RuntimeMXBean.class);
- VirtualMachine virtualmachine = VirtualMachine.attach("5656");
-
- String javaHome = virtualmachine.getSystemProperties().getProperty("java.home");
- String jmxAgent = javaHome + File.separator + "lib" + File.separator + "management-agent.jar";
- virtualmachine.loadAgent(jmxAgent, "com.sun.management.jmxremote");
-
- Properties properties = virtualmachine.getAgentProperties();
- String address = (String)properties.get("com.sun.management.jmxremote.localConnectorAddress");
-
- virtualmachine.detach();
-
- JMXServiceURL url = new JMXServiceURL(address);
- JMXConnector connector = JMXConnectorFactory.connect(url);
- RuntimeMXBean rmxb = <span style="BACKGROUND-COLOR: #00ff40; COLOR: black; " id="casearchresult"><strong>ManagementFactory</strong></span>.newPlatformMXBeanProxy(connector
- .getMBeanServerConnection(), "java.lang:type=Runtime",RuntimeMXBean.class);
3、结束语
能够看到,经过标准的接口,咱们已经能够得到运行的JVM很详细的信息,从运行JVM、操做系统,到内存、GC和线程,经过这些标准的接口咱们已经能够对 JVM进行功能完善的监控。可是仅此是不够的,这部分接口描述的主要是JVM的整体性的信息,而没法提供更多的细节。在下一部分,咱们将使用JPDA来更 深刻地了解JVM内部信息更细节的信息,并了解咱们如何经过JVM TI实现自动的性能监控
软件包 java.lang.management 提供管理接口,用于监视和管理 Java 虚拟机以及 Java 虚拟机在其上运行的操做系统。
它同时容许从本地和远程对正在运行的 Java 虚拟机进行监视和管理。
管理接口
ClassLoadingMXBean Java 虚拟机的类加载系统。
CompilationMXBean Java 虚拟机的编译系统。
MemoryMXBean Java 虚拟机的内存系统。
ThreadMXBean Java 虚拟机的线程系统。
RuntimeMXBean Java 虚拟机的运行时系统。
OperatingSystemMXBean Java 虚拟机在其上运行的操做系统。
GarbageCollectorMXBean Java 虚拟机中的垃圾回收器。
MemoryManagerMXBean Java 虚拟机中的内存管理器。
MemoryPoolMXBean Java 虚拟机中的内存池。
示例以下:
import java.lang.management.ClassLoadingMXBean;
import java.lang.management.CompilationMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.ThreadMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.MemoryPoolMXBean;
import java.util.List;
public class JVM {
public static void main(String[] args) {
//Java 虚拟机线程系统的管理接口 ThreadMXBean
ThreadMXBean th=(ThreadMXBean)ManagementFactory.getThreadMXBean() ;
System.out.println("活动线程的当前数目"+th.getThreadCount());
System.out.println("返回活动守护线程的当前数目"+th.getDaemonThreadCount());
System.out.println("Java 虚拟机启动或峰值重置以来峰值活动线程计数"+th.getPeakThreadCount());
System.out.println("返回当前线程的总 CPU 时间"+th.getCurrentThreadUserTime());
System.out.println("当前线程在用户模式中执行的 CPU 时间"+th.getCurrentThreadUserTime());
//Java 虚拟机的运行时系统的管理接口。 RuntimeMXBean
RuntimeMXBean run=(RuntimeMXBean)ManagementFactory.getRuntimeMXBean();
System.out.println("正在运行的 Java 虚拟机的名称"+run.getName());
System.out.println("Java 虚拟机规范名称"+run.getSpecName());
System.out.println("返回 Java 库路径"+run.getLibraryPath());
System.out.println("系统类加载器用于搜索类文件的 Java 类路径"+run.getClassPath());
//用于操做系统的管理接口,Java 虚拟机在此操做系统上运行 OperatingSystemMXBean
OperatingSystemMXBean op=(OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
System.out.println("返回操做系统的架构"+op.getArch());
System.out.println("返回操做系统名称"+op.getName());
System.out.println("返回操做系统的版本"+op.getVersion());
System.out.println("Java 虚拟机可使用的处理器数目"+op.getAvailableProcessors());
//内存池的管理接口。内存池表示由 Java 虚拟机管理的内存资源,
//由一个或多个内存管理器对内存池进行管理 MemoryPoolMXBean
List<MemoryPoolMXBean> list=ManagementFactory.getMemoryPoolMXBeans();
for(MemoryPoolMXBean mem:list){
System.out.println("Java 虚拟机启动以来或自峰值重置以来此内存池的峰值内存使用量"+mem.getPeakUsage());
System.out.println("返回此内存池的类型"+mem.getType());
System.out.println("内存使用量超过其阈值的次数"+ mem.getUsage());
}
//Java 虚拟机内存系统的管理接口。 MemoryMXBean
MemoryMXBean mem=(MemoryMXBean)ManagementFactory.getMemoryMXBean();
System.out.println(" 返回用于对象分配的堆的当前内存使用量"+mem.getHeapMemoryUsage());
System.out.println("Java 虚拟机使用的非堆内存的当前内存使用量"+mem.getNonHeapMemoryUsage());
// Java 虚拟机的编译系统的管理接口 CompilationMXBean
CompilationMXBean com=(CompilationMXBean)ManagementFactory.getCompilationMXBean();
System.out.println("即时 (JIT) 编译器的名称"+com.getName());
System.out.println("在编译上花费的累积耗费时间的近似值(毫秒)"+com.getTotalCompilationTime());
//Java 虚拟机的类加载系统的管理接口 ClassLoadingMXBean
ClassLoadingMXBean cl=(ClassLoadingMXBean)ManagementFactory.getClassLoadingMXBean();
System.out.println("当前加载到 Java 虚拟机中的类的数量"+cl.getLoadedClassCount());
System.out.println("Java 虚拟机开始执行到目前已经加载的类的总数"+cl.getTotalLoadedClassCount());
System.out.println("Java 虚拟机开始执行到目前已经卸载的类的总数"+cl.getUnloadedClassCount());
}
}
- public class TestExcho {
- public static void main(String[] args) throws Exception{
- MBeanServer server = ManagementFactory.getPlatformMBeanServer();
- ObjectName name = new ObjectName("com.demo.mbean:type=Excho");
- Echo ei =new Echo();
- server.registerMBean(ei,name);
- server.invoke(name, "setName", new Object[] { "jack"}, new String[] {"java.lang.String"});
- server.invoke(name, "showName", null, null);
- String yourName = (String)server.invoke(name, "fetchName", new Object[] { "mimi",10}, new String[] {"java.lang.String","int"});
- System.out.println("~~~"+yourName);
- CompositeData d = (CompositeData) server.invoke(name, "fetchConfig", null, null);
- String fn = (String)d.get("firstName");
- String ln = (String)d.get("lastName");
- System.out.println("~@@@~~"+fn+"@@"+ln);
- int num = (Integer)server.getAttribute(name, "Num");
- System.out.println("~OOOOO~~"+num);
- Thread.currentThread().sleep(Integer.MAX_VALUE);
- }
- }