---------------------
package cn.bisoft.web; import static java.lang.management.ManagementFactory.CLASS_LOADING_MXBEAN_NAME; import static java.lang.management.ManagementFactory.COMPILATION_MXBEAN_NAME; import static java.lang.management.ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE; import static java.lang.management.ManagementFactory.MEMORY_MXBEAN_NAME; import static java.lang.management.ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE; import static java.lang.management.ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME; import static java.lang.management.ManagementFactory.RUNTIME_MXBEAN_NAME; import static java.lang.management.ManagementFactory.THREAD_MXBEAN_NAME; import static java.lang.management.ManagementFactory.newPlatformMXBeanProxy; import java.lang.management.ClassLoadingMXBean; import java.lang.management.CompilationMXBean; import java.lang.management.GarbageCollectorMXBean; import java.lang.management.MemoryMXBean; import java.lang.management.OperatingSystemMXBean; import java.lang.management.RuntimeMXBean; import java.lang.management.ThreadMXBean; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import javax.management.Attribute; import javax.management.AttributeList; import javax.management.MBeanAttributeInfo; import javax.management.MBeanInfo; import javax.management.MBeanOperationInfo; import javax.management.MBeanParameterInfo; import javax.management.MBeanServerConnection; import javax.management.ObjectName; import javax.management.remote.JMXConnector; import javax.management.remote.rmi.RMIConnector; import javax.management.remote.rmi.RMIServer; import javax.rmi.ssl.SslRMIClientSocketFactory; import cn.bisoft.web.proxy.MemoryPoolProxy; public class JMXClient { private String hostName; private int port; private String userName; private String password; private String serviceUrl; private RMIServer stub = null; private JMXConnector jmxc = null; private MBeanServerConnection mbsc = null; private SnapshotMBeanServerConnection server = null; private boolean hasPlatformMXBeans = false; private boolean hasCompilationMXBean = false; private static final SslRMIClientSocketFactory sslRMIClientSocketFactory = new SslRMIClientSocketFactory(); private ClassLoadingMXBean classLoadingMBean = null; private CompilationMXBean compilationMBean = null; private MemoryMXBean memoryMBean = null; private OperatingSystemMXBean operatingSystemMBean = null; private RuntimeMXBean runtimeMBean = null; private ThreadMXBean threadMBean = null; private OperatingSystemMXBean sunOperatingSystemMXBean = null; private ListmemoryPoolProxies = null; private List garbageCollectorMBeans = null; public JMXClient(String hostName, int port, String userName, String password) throws Exception { this.serviceUrl = "service:jmx:rmi:///jndi/rmi://" + hostName + ":" + port + "/jmxrmi"; System.out.println("remote connect address: " + serviceUrl); this.hostName = hostName; this.port = port; this.userName = userName; this.password = password; } public void connect() throws Exception { Registry registry = null; if (null != userName) { registry = LocateRegistry.getRegistry(hostName, port, sslRMIClientSocketFactory); stub = (RMIServer) registry.lookup("jmxrmi"); } else { registry = LocateRegistry.getRegistry(hostName, port); stub = (RMIServer) registry.lookup("jmxrmi"); } if (userName == null && password == null) { this.jmxc = new RMIConnector(stub, null); jmxc.connect(); } else { Map env = new HashMap (); env.put(JMXConnector.CREDENTIALS, new String[] { userName, password }); this.jmxc = new RMIConnector(stub, null); jmxc.connect(env); } this.mbsc = jmxc.getMBeanServerConnection(); this.server = Snapshot.newSnapshot(mbsc); try { ObjectName on = new ObjectName(THREAD_MXBEAN_NAME); this.hasPlatformMXBeans = server.isRegistered(on); if (this.hasPlatformMXBeans) { on = new ObjectName(COMPILATION_MXBEAN_NAME); this.hasCompilationMXBean = server.isRegistered(on); } } catch (Exception e) { e.printStackTrace(); } if (hasPlatformMXBeans) { getRuntimeMXBean(); } System.out.println("Connect JMX Server is Open!"); } public void disconnect() { stub = null; if (jmxc != null) { try { jmxc.close(); } catch (Exception e) { e.printStackTrace(); } } classLoadingMBean = null; compilationMBean = null; memoryMBean = null; operatingSystemMBean = null; runtimeMBean = null; threadMBean = null; sunOperatingSystemMXBean = null; System.out.println("Connect JMX Server is Close!"); } public void flush() { if (server != null) { server.flush(); } } public MBeanServerConnection getMBeanServerConnection() { return mbsc; } public SnapshotMBeanServerConnection getSnapshotMBeanServerConnection() { return server; } public String[] getDomains() throws Exception { return server.getDomains(); } public Map getMBeans(String domain) throws Exception { ObjectName name = null; if (domain != null) { try { name = new ObjectName(domain + ":*"); } catch (Exception e) { e.printStackTrace(); } } Set> mbeans = server.queryNames(name, null); Map result = new HashMap ( mbeans.size()); Iterator> iterator = mbeans.iterator(); while (iterator.hasNext()) { Object object = iterator.next(); if (object instanceof ObjectName) { ObjectName o = (ObjectName) object; try { MBeanInfo info = server.getMBeanInfo(o); result.put(o, info); } catch (Exception e) { e.printStackTrace(); } } } return result; } public AttributeList getAttributes(ObjectName name, String[] attributes) throws Exception { AttributeList list = null; try { list = server.getAttributes(name, attributes); } catch (Exception e) { e.printStackTrace(); } return list; } public void setAttribute(ObjectName name, Attribute attribute) throws Exception { try { server.setAttribute(name, attribute); } catch (Exception e) { e.printStackTrace(); } } public Object invoke(ObjectName name, String operationName, Object[] params, String[] signature) throws Exception { Object result = null; try { result = server.invoke(name, operationName, params, signature); } catch (Exception e) { e.printStackTrace(); } return result; } public T getMXBean(ObjectName objName, Class interfaceClass) throws Exception { return newPlatformMXBeanProxy(server, objName.toString(), interfaceClass); } public String[] getSignature(MBeanOperationInfo operation) { MBeanParameterInfo params[] = operation.getSignature(); String result[] = new String[params.length]; for (int i = 0; i < params.length; i++) { result[i] = params[i].getType(); } return result; } boolean hasPlatformMXBeans() { return this.hasPlatformMXBeans; } public boolean isRegistered(ObjectName name) throws Exception { return server.isRegistered(name); } public synchronized ClassLoadingMXBean getClassLoadingMXBean() throws Exception { if (hasPlatformMXBeans && classLoadingMBean == null) { classLoadingMBean = newPlatformMXBeanProxy(server, CLASS_LOADING_MXBEAN_NAME, ClassLoadingMXBean.class); } return classLoadingMBean; } public synchronized CompilationMXBean getCompilationMXBean() throws Exception { if (hasCompilationMXBean && compilationMBean == null) { compilationMBean = newPlatformMXBeanProxy(server, COMPILATION_MXBEAN_NAME, CompilationMXBean.class); } return compilationMBean; } public Collection getMemoryPoolProxies() throws Exception { if (memoryPoolProxies == null) { ObjectName poolName = null; try { poolName = new ObjectName(MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",*"); } catch (Exception e) { e.printStackTrace(); } Set> mbeans = server.queryNames(poolName, null); if (mbeans != null) { memoryPoolProxies = new ArrayList (); Iterator> iterator = mbeans.iterator(); while (iterator.hasNext()) { ObjectName objName = (ObjectName) iterator.next(); MemoryPoolProxy p = new MemoryPoolProxy(this, objName); memoryPoolProxies.add(p); } } } return memoryPoolProxies; } public synchronized Collection getGarbageCollectorMXBeans() throws Exception { if (garbageCollectorMBeans == null) { ObjectName gcName = null; try { gcName = new ObjectName(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",*"); } catch (Exception e) { e.printStackTrace(); } Set> mbeans = server.queryNames(gcName, null); if (mbeans != null) { garbageCollectorMBeans = new ArrayList (); Iterator> iterator = mbeans.iterator(); while (iterator.hasNext()) { ObjectName on = (ObjectName) iterator.next(); String name = GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",name=" + on.getKeyProperty("name"); GarbageCollectorMXBean mBean = newPlatformMXBeanProxy( server, name, GarbageCollectorMXBean.class); garbageCollectorMBeans.add(mBean); } } } return garbageCollectorMBeans; } public synchronized MemoryMXBean getMemoryMXBean() throws Exception { if (hasPlatformMXBeans && memoryMBean == null) { memoryMBean = newPlatformMXBeanProxy(server, MEMORY_MXBEAN_NAME, MemoryMXBean.class); } return memoryMBean; } public synchronized RuntimeMXBean getRuntimeMXBean() throws Exception { if (hasPlatformMXBeans && runtimeMBean == null) { runtimeMBean = newPlatformMXBeanProxy(server, RUNTIME_MXBEAN_NAME, RuntimeMXBean.class); } return runtimeMBean; } public synchronized ThreadMXBean getThreadMXBean() throws Exception { if (hasPlatformMXBeans && threadMBean == null) { threadMBean = newPlatformMXBeanProxy(server, THREAD_MXBEAN_NAME, ThreadMXBean.class); } return threadMBean; } public synchronized OperatingSystemMXBean getOperatingSystemMXBean() throws Exception { if (hasPlatformMXBeans && operatingSystemMBean == null) { operatingSystemMBean = newPlatformMXBeanProxy(server, OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class); } return operatingSystemMBean; } public synchronized OperatingSystemMXBean getSunOperatingSystemMXBean() throws Exception { try { ObjectName on = new ObjectName(OPERATING_SYSTEM_MXBEAN_NAME); if (sunOperatingSystemMXBean == null) { if (server.isInstanceOf(on, "com.sun.management.OperatingSystemMXBean")) { sunOperatingSystemMXBean = newPlatformMXBeanProxy(server, OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class); } } } catch (Exception e) { return null; } return sunOperatingSystemMXBean; } public static class Snapshot { private Snapshot() { } public static SnapshotMBeanServerConnection newSnapshot( MBeanServerConnection mbsc) { final InvocationHandler ih = new SnapshotInvocationHandler(mbsc); return (SnapshotMBeanServerConnection) Proxy.newProxyInstance( Snapshot.class.getClassLoader(), new Class[] { SnapshotMBeanServerConnection.class }, ih); } } public interface SnapshotMBeanServerConnection extends MBeanServerConnection { public void flush(); } static class SnapshotInvocationHandler implements InvocationHandler { private final MBeanServerConnection conn; private Map cachedValues = newMap(); private Map > cachedNames = newMap(); @SuppressWarnings("serial") private static final class NameValueMap extends HashMap { } SnapshotInvocationHandler(MBeanServerConnection conn) { this.conn = conn; } synchronized void flush() { cachedValues = newMap(); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { final String methodName = method.getName(); if (methodName.equals("getAttribute")) { return getAttribute((ObjectName) args[0], (String) args[1]); } else if (methodName.equals("getAttributes")) { return getAttributes((ObjectName) args[0], (String[]) args[1]); } else if (methodName.equals("flush")) { flush(); return null; } else { try { return method.invoke(conn, args); } catch (InvocationTargetException e) { throw e.getCause(); } } } private Object getAttribute(ObjectName objName, String attrName) throws Exception { final NameValueMap values = getCachedAttributes(objName, Collections.singleton(attrName)); Object value = values.get(attrName); if (value != null || values.containsKey(attrName)) { return value; } return conn.getAttribute(objName, attrName); } private AttributeList getAttributes(ObjectName objName, String[] attrNames) throws Exception { final NameValueMap values = getCachedAttributes(objName, new TreeSet (Arrays.asList(attrNames))); final AttributeList list = new AttributeList(); for (String attrName : attrNames) { final Object value = values.get(attrName); if (value != null || values.containsKey(attrName)) { list.add(new Attribute(attrName, value)); } } return list; } private synchronized NameValueMap getCachedAttributes( ObjectName objName, Set attrNames) throws Exception { NameValueMap values = cachedValues.get(objName); if (values != null && values.keySet().containsAll(attrNames)) { return values; } attrNames = new TreeSet (attrNames); Set oldNames = cachedNames.get(objName); if (oldNames != null) { attrNames.addAll(oldNames); } values = new NameValueMap(); final AttributeList attrs = conn.getAttributes(objName, attrNames.toArray(new String[attrNames.size()])); Iterator> it = attrs.listIterator(); while (it.hasNext()) { Attribute attribute = (Attribute) it.next(); values.put(attribute.getName(), attribute.getValue()); } cachedValues.put(objName, values); cachedNames.put(objName, attrNames); return values; } private static Map newMap() { return new HashMap (); } } public String getHostName() { return hostName; } public void setHostName(String hostName) { this.hostName = hostName; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getServiceUrl() { return serviceUrl; } public void setServiceUrl(String serviceUrl) { this.serviceUrl = serviceUrl; } public RMIServer getStub() { return stub; } public void setStub(RMIServer stub) { this.stub = stub; } public JMXConnector getJmxc() { return jmxc; } public void setJmxc(JMXConnector jmxc) { this.jmxc = jmxc; } public MBeanServerConnection getMbsc() { return mbsc; } public void setMbsc(MBeanServerConnection mbsc) { this.mbsc = mbsc; } public SnapshotMBeanServerConnection getServer() { return server; } public void setServer(SnapshotMBeanServerConnection server) { this.server = server; } /** * 远程连接JMX Server,但有用户名和密码的情况下没有连接成功. */ public static void main(String[] args) throws Exception { JMXClient client = new JMXClient("127.0.0.1", 1090, null, null); // 开始连接 client.connect(); // 查询MBean信息 for (String domain : client.getDomains()) { System.out.println(domain); Map mbeanMap = client.getMBeans(domain); for (Map.Entry entry : mbeanMap.entrySet()) { System.out.println(" " + "ObjectName=" + entry.getKey()); System.out.println(" " + "MBeanInfo=" + entry.getValue().getClassName()); System.out.println(" " + "MBeanInfo=" + entry.getValue().getAttributes()); for (MBeanAttributeInfo mBeanAttributeInfo : entry.getValue() .getAttributes()) { System.out.println(" " + "Attribute=" + mBeanAttributeInfo.getName()); } System.out.println(" " + "MBeanInfo=" + entry.getValue().getOperations()); for (MBeanOperationInfo mBeanOperationInfo : entry.getValue() .getOperations()) { System.out.println(" " + "Operation=" + mBeanOperationInfo.getName()); // 调用MBean方法 if (mBeanOperationInfo.getName().equals("getLoggerLevel")) { Object obj = client.invoke(entry.getKey(), "getLoggerLevel", new Object[] { "" }, client.getSignature(mBeanOperationInfo)); System.out .println("call getLoggerLevel result: " + obj); } } } } } }
package cn.bisoft.web.proxy; import static java.lang.management.ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE; import java.lang.management.MemoryPoolMXBean; import java.lang.management.MemoryUsage; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.management.ObjectName; import cn.bisoft.web.JMXClient; import com.sun.management.GarbageCollectorMXBean; import com.sun.management.GcInfo; @SuppressWarnings("restriction") public class MemoryPoolProxy { private String poolName; private JMXClient client; private ObjectName objName; private MemoryPoolMXBean pool; private MapgcMBeans; private GcInfo lastGcInfo; public MemoryPoolProxy(JMXClient client, ObjectName poolName) throws Exception { this.client = client; this.pool = client.getMXBean(poolName, MemoryPoolMXBean.class); this.poolName = this.pool.getName(); this.gcMBeans = new HashMap (); this.lastGcInfo = null; String[] mgrNames = pool.getMemoryManagerNames(); for (String name : mgrNames) { try { ObjectName mbeanName = new ObjectName( GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",name=" + name); if (client.isRegistered(mbeanName)) { gcMBeans.put(mbeanName, new Long(0)); } } catch (Exception e) { assert false; } } } public boolean isCollectedMemoryPool() { return (gcMBeans.size() != 0); } public ObjectName getObjectName() { return objName; } public MemoryPoolStat getStat() throws Exception { long usageThreshold = (pool.isUsageThresholdSupported() ? pool .getUsageThreshold() : -1); long collectThreshold = (pool.isCollectionUsageThresholdSupported() ? pool .getCollectionUsageThreshold() : -1); long lastGcStartTime = 0; long lastGcEndTime = 0; MemoryUsage beforeGcUsage = null; MemoryUsage afterGcUsage = null; long gcId = 0; if (lastGcInfo != null) { gcId = lastGcInfo.getId(); lastGcStartTime = lastGcInfo.getStartTime(); lastGcEndTime = lastGcInfo.getEndTime(); beforeGcUsage = lastGcInfo.getMemoryUsageBeforeGc().get(poolName); afterGcUsage = lastGcInfo.getMemoryUsageAfterGc().get(poolName); } Set > set = gcMBeans.entrySet(); for (Map.Entry e : set) { GarbageCollectorMXBean gc = client.getMXBean(e.getKey(), com.sun.management.GarbageCollectorMXBean.class); Long gcCount = e.getValue(); Long newCount = gc.getCollectionCount(); if (newCount > gcCount) { gcMBeans.put(e.getKey(), new Long(newCount)); lastGcInfo = gc.getLastGcInfo(); if (lastGcInfo.getEndTime() > lastGcEndTime) { gcId = lastGcInfo.getId(); lastGcStartTime = lastGcInfo.getStartTime(); lastGcEndTime = lastGcInfo.getEndTime(); beforeGcUsage = lastGcInfo.getMemoryUsageBeforeGc().get( poolName); afterGcUsage = lastGcInfo.getMemoryUsageAfterGc().get( poolName); assert (beforeGcUsage != null); assert (afterGcUsage != null); } } } MemoryUsage usage = pool.getUsage(); return new MemoryPoolStat(poolName, usageThreshold, usage, gcId, lastGcStartTime, lastGcEndTime, collectThreshold, beforeGcUsage, afterGcUsage); } public String getPoolName() { return poolName; } public void setPoolName(String poolName) { this.poolName = poolName; } public JMXClient getClient() { return client; } public void setClient(JMXClient client) { this.client = client; } public ObjectName getObjName() { return objName; } public void setObjName(ObjectName objName) { this.objName = objName; } public MemoryPoolMXBean getPool() { return pool; } public void setPool(MemoryPoolMXBean pool) { this.pool = pool; } public Map getGcMBeans() { return gcMBeans; } public void setGcMBeans(Map gcMBeans) { this.gcMBeans = gcMBeans; } public GcInfo getLastGcInfo() { return lastGcInfo; } public void setLastGcInfo(GcInfo lastGcInfo) { this.lastGcInfo = lastGcInfo; } }
package cn.bisoft.web.proxy; import java.lang.management.MemoryUsage; public class MemoryPoolStat { private String poolName; private long usageThreshold; private MemoryUsage usage; private long lastGcId; private long lastGcStartTime; private long lastGcEndTime; private long collectThreshold; private MemoryUsage beforeGcUsage; private MemoryUsage afterGcUsage; MemoryPoolStat(String name, long usageThreshold, MemoryUsage usage, long lastGcId, long lastGcStartTime, long lastGcEndTime, long collectThreshold, MemoryUsage beforeGcUsage, MemoryUsage afterGcUsage) { this.poolName = name; this.usageThreshold = usageThreshold; this.usage = usage; this.lastGcId = lastGcId; this.lastGcStartTime = lastGcStartTime; this.lastGcEndTime = lastGcEndTime; this.collectThreshold = collectThreshold; this.beforeGcUsage = beforeGcUsage; this.afterGcUsage = afterGcUsage; } public String getPoolName() { return poolName; } public MemoryUsage getUsage() { return usage; } public long getUsageThreshold() { return usageThreshold; } public long getCollectionUsageThreshold() { return collectThreshold; } public long getLastGcId() { return lastGcId; } public long getLastGcStartTime() { return lastGcStartTime; } public long getLastGcEndTime() { return lastGcEndTime; } public MemoryUsage getBeforeGcUsage() { return beforeGcUsage; } public MemoryUsage getAfterGcUsage() { return afterGcUsage; } public long getCollectThreshold() { return collectThreshold; } public void setCollectThreshold(long collectThreshold) { this.collectThreshold = collectThreshold; } public void setPoolName(String poolName) { this.poolName = poolName; } public void setUsageThreshold(long usageThreshold) { this.usageThreshold = usageThreshold; } public void setUsage(MemoryUsage usage) { this.usage = usage; } public void setLastGcId(long lastGcId) { this.lastGcId = lastGcId; } public void setLastGcStartTime(long lastGcStartTime) { this.lastGcStartTime = lastGcStartTime; } public void setLastGcEndTime(long lastGcEndTime) { this.lastGcEndTime = lastGcEndTime; } public void setBeforeGcUsage(MemoryUsage beforeGcUsage) { this.beforeGcUsage = beforeGcUsage; } public void setAfterGcUsage(MemoryUsage afterGcUsage) { this.afterGcUsage = afterGcUsage; } }
结果:
remote connect address: service:jmx:rmi:///jndi/rmi://127.0.0.1:1090/jmxrmi Connect JMX Server is Open! JMImplementation ObjectName=JMImplementation:type=MBeanServerDelegate MBeanInfo=javax.management.MBeanServerDelegate MBeanInfo=[Ljavax.management.MBeanAttributeInfo;@8814e9 Attribute=MBeanServerId Attribute=SpecificationName Attribute=SpecificationVersion Attribute=SpecificationVendor Attribute=ImplementationName Attribute=ImplementationVersion Attribute=ImplementationVendor MBeanInfo=[Ljavax.management.MBeanOperationInfo;@1a1c887 java.util.logging ObjectName=java.util.logging:type=Logging MBeanInfo=sun.management.ManagementFactoryHelper$PlatformLoggingImpl MBeanInfo=[Ljavax.management.MBeanAttributeInfo;@1430b5c Attribute=ObjectName Attribute=LoggerNames MBeanInfo=[Ljavax.management.MBeanOperationInfo;@9ed927 Operation=getLoggerLevel call getLoggerLevel result: Operation=getParentLoggerName Operation=setLoggerLevel ...........
服务端使用TOMCAT
catalina.bat
set JAVA_OPTS=%JAVA_OPTS% %LOGGING_MANAGER% :jmx set JMX_SSL=-Dcom.sun.management.jmxremote.ssl=false set JMX_AUTH=-Dcom.sun.management.jmxremote.authenticate=false rem set JMX_AUTH_USER=-Dcom.sun.management.jmxremote.acccess.file="E:/bisoft/tools/tomcat7/conf/jmxremote.access" rem set JMX_AUTH_PASSWORD=-Dcom.sun.management.jmxremote.password.file="E:/bisoft/tools/tomcat7/conf/jmxremote.password" set JMX_SERVICE_URL=-Djava.rmi.server.hostname="127.0.0.1" -Dcom.sun.management.jmxremote.port=1090 set JMX_OPTS=%JMX_SSL% %JMX_AUTH% %JMX_SERVICE_URL%