(userName == null ? "" : userName) + ":" + (password == null ? "" : password); } public String connectionName() { return connectionName; } public String getDisplayName() { return displayName; } public String toString() { if (!isConnected()) { return Resources.getText("ConnectionName (disconnected)", displayName); } else { return displayName; } } public MBeanServerConnection getMBeanServerConnection() { return mbsc; } public SnapshotMBeanServerConnection getSnapshotMBeanServerConnection() { return server; } public String getUrl() { return advancedUrl; } public String getHostName() { return hostName; } public int getPort() { return port; } public int getVmid() { return (lvm != null) ? lvm.vmid() : 0; } public String getUserName() { return userName; } public String getPassword() { return password; } public void disconnect() { // Reset remote stub stub = null; // Close MBeanServer connection if (jmxc != null) { try { jmxc.close(); } catch (IOException e) { // Ignore ??? } } // Reset platform MBean references classLoadingMBean = null; compilationMBean = null; memoryMBean = null; operatingSystemMBean = null; runtimeMBean = null; threadMBean = null; sunOperatingSystemMXBean = null; garbageCollectorMBeans = null; // Set connection state to DISCONNECTED if (!isDead) { isDead = true; setConnectionState(ConnectionState.DISCONNECTED); } } /** * Returns the list of domains in which any MBean is * currently registered. */ public String[] getDomains() throws IOException { return server.getDomains(); } /** * Returns a map of MBeans with ObjectName as the key and MBeanInfo value * of a given domain. If domain is <tt>null</tt>, all MBeans * are returned. If no MBean found, an empty map is returned. * */ public Map<ObjectName, MBeanInfo> getMBeans(String domain) throws IOException { ObjectName name = null; if (domain != null) { try { name = new ObjectName(domain + ":*"); } catch (MalformedObjectNameException e) { // should not reach here assert(false); } } Set mbeans = server.queryNames(name, null); Map<ObjectName,MBeanInfo> result = new HashMap<ObjectName,MBeanInfo>(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 (IntrospectionException e) { // TODO: should log the error } catch (InstanceNotFoundException e) { // TODO: should log the error } catch (ReflectionException e) { // TODO: should log the error } } } return result; } /** * Returns a list of attributes of a named MBean. * */ public AttributeList getAttributes(ObjectName name, String[] attributes) throws IOException { AttributeList list = null; try { list = server.getAttributes(name, attributes); } catch (InstanceNotFoundException e) { // TODO: A MBean may have been unregistered. // need to set up listener to listen for MBeanServerNotification. } catch (ReflectionException e) { // TODO: should log the error } return list; } /** * Set the value of a specific attribute of a named MBean. */ public void setAttribute(ObjectName name, Attribute attribute) throws InvalidAttributeValueException, MBeanException, IOException { try { server.setAttribute(name, attribute); } catch (InstanceNotFoundException e) { // TODO: A MBean may have been unregistered. } catch (AttributeNotFoundException e) { assert(false); } catch (ReflectionException e) { // TODO: should log the error } } /** * Invokes an operation of a named MBean. * * @throws MBeanException Wraps an exception thrown by * the MBean's invoked method. */ public Object invoke(ObjectName name, String operationName, Object[] params, String[] signature) throws IOException, MBeanException { Object result = null; try { result = server.invoke(name, operationName, params, signature); } catch (InstanceNotFoundException e) { // TODO: A MBean may have been unregistered. } catch (ReflectionException e) { // TODO: should log the error } return result; } public synchronized ClassLoadingMXBean getClassLoadingMXBean() throws IOException { if (hasPlatformMXBeans && classLoadingMBean == null) { classLoadingMBean = newPlatformMXBeanProxy(server, CLASS_LOADING_MXBEAN_NAME, ClassLoadingMXBean.class); } return classLoadingMBean; } public synchronized CompilationMXBean getCompilationMXBean() throws IOException { if (hasCompilationMXBean && compilationMBean == null) { compilationMBean = newPlatformMXBeanProxy(server, COMPILATION_MXBEAN_NAME, CompilationMXBean.class); } return compilationMBean; } public Collection<MemoryPoolProxy> getMemoryPoolProxies() throws IOException { // TODO: How to deal with changes to the list?? if (memoryPoolProxies == null) { ObjectName poolName = null; try { poolName = new ObjectName(MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",*"); } catch (MalformedObjectNameException e) { // should not reach here assert(false); } Set mbeans = server.queryNames(poolName, null); if (mbeans != null) { memoryPoolProxies = new ArrayList<MemoryPoolProxy>(); 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<GarbageCollectorMXBean> getGarbageCollectorMXBeans() throws IOException { // TODO: How to deal with changes to the list?? if (garbageCollectorMBeans == null) { ObjectName gcName = null; try { gcName = new ObjectName(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",*"); } catch (MalformedObjectNameException e) { // should not reach here assert(false); } Set mbeans = server.queryNames(gcName, null); if (mbeans != null) { garbageCollectorMBeans = new ArrayList<GarbageCollectorMXBean>(); 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 IOException { if (hasPlatformMXBeans && memoryMBean == null) { memoryMBean = newPlatformMXBeanProxy(server, MEMORY_MXBEAN_NAME, MemoryMXBean.class); } return memoryMBean; } public synchronized RuntimeMXBean getRuntimeMXBean() throws IOException { if (hasPlatformMXBeans && runtimeMBean == null) { runtimeMBean = newPlatformMXBeanProxy(server, RUNTIME_MXBEAN_NAME, RuntimeMXBean.class); } return runtimeMBean; } public synchronized ThreadMXBean getThreadMXBean() throws IOException { if (hasPlatformMXBeans && threadMBean == null) { threadMBean = newPlatformMXBeanProxy(server, THREAD_MXBEAN_NAME, ThreadMXBean.class); } return threadMBean; } public synchronized OperatingSystemMXBean getOperatingSystemMXBean() throws IOException { if (hasPlatformMXBeans && operatingSystemMBean == null) { operatingSystemMBean = newPlatformMXBeanProxy(server, OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class); } return operatingSystemMBean; } public synchronized com.sun.management.OperatingSystemMXBean getSunOperatingSystemMXBean() throws IOException { 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, com.sun.management.OperatingSystemMXBean.class); } } } catch (InstanceNotFoundException e) { return null; } catch (MalformedObjectNameException e) { return null; // should never reach here } return sunOperatingSystemMXBean; } public synchronized HotSpotDiagnosticMXBean getHotSpotDiagnosticMXBean() throws IOException { if (hasHotSpotDiagnosticMXBean && hotspotDiagnosticMXBean == null) { hotspotDiagnosticMXBean = newPlatformMXBeanProxy(server, HOTSPOT_DIAGNOSTIC_MXBEAN_NAME, HotSpotDiagnosticMXBean.class); } return hotspotDiagnosticMXBean; } public <T> T getMXBean(ObjectName objName, Class<T> interfaceClass) throws IOException { return newPlatformMXBeanProxy(server, objName.toString(), interfaceClass); } // Return thread IDs of deadlocked threads or null if any. // It finds deadlocks involving only monitors if it's a Tiger VM. // Otherwise, it finds deadlocks involving both monitors and // the concurrent locks. public long[] findDeadlockedThreads() throws IOException { ThreadMXBean tm = getThreadMXBean(); if (supportsLockUsage && tm.isSynchronizerUsageSupported()) { return tm.findDeadlockedThreads(); } else { return tm.findMonitorDeadlockedThreads(); } } public synchronized void markAsDead() { disconnect(); } public boolean isDead() { return isDead; } boolean isConnected() { return !isDead(); } boolean hasPlatformMXBeans() { return this.hasPlatformMXBeans; } boolean hasHotSpotDiagnosticMXBean() { return this.hasHotSpotDiagnosticMXBean; } boolean isLockUsageSupported() { return supportsLockUsage; } public boolean isRegistered(ObjectName name) throws IOException { return server.isRegistered(name); } public void addPropertyChangeListener(PropertyChangeListener listener) { propertyChangeSupport.addPropertyChangeListener(listener); } public void addWeakPropertyChangeListener(PropertyChangeListener listener) { if (!(listener instanceof WeakPCL)) { listener = new WeakPCL(listener); } propertyChangeSupport.addPropertyChangeListener(listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { if (!(listener instanceof WeakPCL)) { // Search for the WeakPCL holding this listener (if any) for (PropertyChangeListener pcl : propertyChangeSupport.getPropertyChangeListeners()) { if (pcl instanceof WeakPCL && ((WeakPCL)pcl).get() == listener) { listener = pcl; break; } } } propertyChangeSupport.removePropertyChangeListener(listener); } /** * The PropertyChangeListener is handled via a WeakReference * so as not to pin down the listener. */ private class WeakPCL extends WeakReference<PropertyChangeListener> implements PropertyChangeListener { WeakPCL(PropertyChangeListener referent) { super(referent); } public void propertyChange(PropertyChangeEvent pce) { PropertyChangeListener pcl = get(); if (pcl == null) { // The referent listener was GC'ed, we're no longer // interested in PropertyChanges, remove the listener. dispose(); } else { pcl.propertyChange(pce); } } private void dispose() { removePropertyChangeListener(this); } } // // Snapshot MBeanServerConnection: // // This is an object that wraps an existing MBeanServerConnection and adds // caching to it, as follows: // // - The first time an attribute is called in a given MBean, the result is // cached. Every subsequent time getAttribute is called for that attribute // the cached result is returned. // // - Before every call to VMPanel.update() or when the Refresh button in the // Attributes table is pressed down the attributes cache is flushed. Then // any subsequent call to getAttribute will retrieve all the values for // the attributes that are known to the cache. // // - The attributes cache uses a learning approach and only the attributes // that are in the cache will be retrieved between two subsequent updates. // public interface SnapshotMBeanServerConnection extends MBeanServerConnection { /** * Flush all cached values of attributes. */ public void flush(); } 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); } } static class SnapshotInvocationHandler implements InvocationHandler { private final MBeanServerConnection conn; private Map<ObjectName, NameValueMap> cachedValues = newMap(); private Map<ObjectName, Set<String>> cachedNames = newMap(); @SuppressWarnings("serial") private static final class NameValueMap extends HashMap<String, Object> {} 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();Lines 501–1000 of 1065. Previous lines Load more
(userName == null ? "" : userName) + ":" + (password == null ? "" : password); } public String connectionName() { return connectionName; } public String getDisplayName() { return displayName; } public String toString() { if (!isConnected()) { return Resources.getText("ConnectionName (disconnected)", displayName); } else { return displayName; } } public MBeanServerConnection getMBeanServerConnection() { return mbsc; } public SnapshotMBeanServerConnection getSnapshotMBeanServerConnection() { return server; } public String getUrl() { return advancedUrl; } public String getHostName() { return hostName; } public int getPort() { return port; } public int getVmid() { return (lvm != null) ? lvm.vmid() : 0; } public String getUserName() { return userName; } public String getPassword() { return password; } public void disconnect() { // Reset remote stub stub = null; // Close MBeanServer connection if (jmxc != null) { try { jmxc.close(); } catch (IOException e) { // Ignore ??? } } // Reset platform MBean references classLoadingMBean = null; compilationMBean = null; memoryMBean = null; operatingSystemMBean = null; runtimeMBean = null; threadMBean = null; sunOperatingSystemMXBean = null; garbageCollectorMBeans = null; // Set connection state to DISCONNECTED if (!isDead) { isDead = true; setConnectionState(ConnectionState.DISCONNECTED); } } /** * Returns the list of domains in which any MBean is * currently registered. */ public String[] getDomains() throws IOException { return server.getDomains(); } /** * Returns a map of MBeans with ObjectName as the key and MBeanInfo value * of a given domain. If domain is <tt>null</tt>, all MBeans * are returned. If no MBean found, an empty map is returned. * */ public Map<ObjectName, MBeanInfo> getMBeans(String domain) throws IOException { ObjectName name = null; if (domain != null) { try { name = new ObjectName(domain + ":*"); } catch (MalformedObjectNameException e) { // should not reach here assert(false); } } Set mbeans = server.queryNames(name, null); Map<ObjectName,MBeanInfo> result = new HashMap<ObjectName,MBeanInfo>(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 (IntrospectionException e) { // TODO: should log the error } catch (InstanceNotFoundException e) { // TODO: should log the error } catch (ReflectionException e) { // TODO: should log the error } } } return result; } /** * Returns a list of attributes of a named MBean. * */ public AttributeList getAttributes(ObjectName name, String[] attributes) throws IOException { AttributeList list = null; try { list = server.getAttributes(name, attributes); } catch (InstanceNotFoundException e) { // TODO: A MBean may have been unregistered. // need to set up listener to listen for MBeanServerNotification. } catch (ReflectionException e) { // TODO: should log the error } return list; } /** * Set the value of a specific attribute of a named MBean. */ public void setAttribute(ObjectName name, Attribute attribute) throws InvalidAttributeValueException, MBeanException, IOException { try { server.setAttribute(name, attribute); } catch (InstanceNotFoundException e) { // TODO: A MBean may have been unregistered. } catch (AttributeNotFoundException e) { assert(false); } catch (ReflectionException e) { // TODO: should log the error } } /** * Invokes an operation of a named MBean. * * @throws MBeanException Wraps an exception thrown by * the MBean's invoked method. */ public Object invoke(ObjectName name, String operationName, Object[] params, String[] signature) throws IOException, MBeanException { Object result = null; try { result = server.invoke(name, operationName, params, signature); } catch (InstanceNotFoundException e) { // TODO: A MBean may have been unregistered. } catch (ReflectionException e) { // TODO: should log the error } return result; } public synchronized ClassLoadingMXBean getClassLoadingMXBean() throws IOException { if (hasPlatformMXBeans && classLoadingMBean == null) { classLoadingMBean = newPlatformMXBeanProxy(server, CLASS_LOADING_MXBEAN_NAME, ClassLoadingMXBean.class); } return classLoadingMBean; } public synchronized CompilationMXBean getCompilationMXBean() throws IOException { if (hasCompilationMXBean && compilationMBean == null) { compilationMBean = newPlatformMXBeanProxy(server, COMPILATION_MXBEAN_NAME, CompilationMXBean.class); } return compilationMBean; } public Collection<MemoryPoolProxy> getMemoryPoolProxies() throws IOException { // TODO: How to deal with changes to the list?? if (memoryPoolProxies == null) { ObjectName poolName = null; try { poolName = new ObjectName(MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",*"); } catch (MalformedObjectNameException e) { // should not reach here assert(false); } Set mbeans = server.queryNames(poolName, null); if (mbeans != null) { memoryPoolProxies = new ArrayList<MemoryPoolProxy>(); 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<GarbageCollectorMXBean> getGarbageCollectorMXBeans() throws IOException { // TODO: How to deal with changes to the list?? if (garbageCollectorMBeans == null) { ObjectName gcName = null; try { gcName = new ObjectName(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",*"); } catch (MalformedObjectNameException e) { // should not reach here assert(false); } Set mbeans = server.queryNames(gcName, null); if (mbeans != null) { garbageCollectorMBeans = new ArrayList<GarbageCollectorMXBean>(); 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 IOException { if (hasPlatformMXBeans && memoryMBean == null) { memoryMBean = newPlatformMXBeanProxy(server, MEMORY_MXBEAN_NAME, MemoryMXBean.class); } return memoryMBean; } public synchronized RuntimeMXBean getRuntimeMXBean() throws IOException { if (hasPlatformMXBeans && runtimeMBean == null) { runtimeMBean = newPlatformMXBeanProxy(server, RUNTIME_MXBEAN_NAME, RuntimeMXBean.class); } return runtimeMBean; } public synchronized ThreadMXBean getThreadMXBean() throws IOException { if (hasPlatformMXBeans && threadMBean == null) { threadMBean = newPlatformMXBeanProxy(server, THREAD_MXBEAN_NAME, ThreadMXBean.class); } return threadMBean; } public synchronized OperatingSystemMXBean getOperatingSystemMXBean() throws IOException { if (hasPlatformMXBeans && operatingSystemMBean == null) { operatingSystemMBean = newPlatformMXBeanProxy(server, OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class); } return operatingSystemMBean; } public synchronized com.sun.management.OperatingSystemMXBean getSunOperatingSystemMXBean() throws IOException { 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, com.sun.management.OperatingSystemMXBean.class); } } } catch (InstanceNotFoundException e) { return null; } catch (MalformedObjectNameException e) { return null; // should never reach here } return sunOperatingSystemMXBean; } public synchronized HotSpotDiagnosticMXBean getHotSpotDiagnosticMXBean() throws IOException { if (hasHotSpotDiagnosticMXBean && hotspotDiagnosticMXBean == null) { hotspotDiagnosticMXBean = newPlatformMXBeanProxy(server, HOTSPOT_DIAGNOSTIC_MXBEAN_NAME, HotSpotDiagnosticMXBean.class); } return hotspotDiagnosticMXBean; } public <T> T getMXBean(ObjectName objName, Class<T> interfaceClass) throws IOException { return newPlatformMXBeanProxy(server, objName.toString(), interfaceClass); } // Return thread IDs of deadlocked threads or null if any. // It finds deadlocks involving only monitors if it's a Tiger VM. // Otherwise, it finds deadlocks involving both monitors and // the concurrent locks. public long[] findDeadlockedThreads() throws IOException { ThreadMXBean tm = getThreadMXBean(); if (supportsLockUsage && tm.isSynchronizerUsageSupported()) { return tm.findDeadlockedThreads(); } else { return tm.findMonitorDeadlockedThreads(); } } public synchronized void markAsDead() { disconnect(); } public boolean isDead() { return isDead; } boolean isConnected() { return !isDead(); } boolean hasPlatformMXBeans() { return this.hasPlatformMXBeans; } boolean hasHotSpotDiagnosticMXBean() { return this.hasHotSpotDiagnosticMXBean; } boolean isLockUsageSupported() { return supportsLockUsage; } public boolean isRegistered(ObjectName name) throws IOException { return server.isRegistered(name); } public void addPropertyChangeListener(PropertyChangeListener listener) { propertyChangeSupport.addPropertyChangeListener(listener); } public void addWeakPropertyChangeListener(PropertyChangeListener listener) { if (!(listener instanceof WeakPCL)) { listener = new WeakPCL(listener); } propertyChangeSupport.addPropertyChangeListener(listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { if (!(listener instanceof WeakPCL)) { // Search for the WeakPCL holding this listener (if any) for (PropertyChangeListener pcl : propertyChangeSupport.getPropertyChangeListeners()) { if (pcl instanceof WeakPCL && ((WeakPCL)pcl).get() == listener) { listener = pcl; break; } } } propertyChangeSupport.removePropertyChangeListener(listener); } /** * The PropertyChangeListener is handled via a WeakReference * so as not to pin down the listener. */ private class WeakPCL extends WeakReference<PropertyChangeListener> implements PropertyChangeListener { WeakPCL(PropertyChangeListener referent) { super(referent); } public void propertyChange(PropertyChangeEvent pce) { PropertyChangeListener pcl = get(); if (pcl == null) { // The referent listener was GC'ed, we're no longer // interested in PropertyChanges, remove the listener. dispose(); } else { pcl.propertyChange(pce); } } private void dispose() { removePropertyChangeListener(this); } } // // Snapshot MBeanServerConnection: // // This is an object that wraps an existing MBeanServerConnection and adds // caching to it, as follows: // // - The first time an attribute is called in a given MBean, the result is // cached. Every subsequent time getAttribute is called for that attribute // the cached result is returned. // // - Before every call to VMPanel.update() or when the Refresh button in the // Attributes table is pressed down the attributes cache is flushed. Then // any subsequent call to getAttribute will retrieve all the values for // the attributes that are known to the cache. // // - The attributes cache uses a learning approach and only the attributes // that are in the cache will be retrieved between two subsequent updates. // public interface SnapshotMBeanServerConnection extends MBeanServerConnection { /** * Flush all cached values of attributes. */ public void flush(); } 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); } } static class SnapshotInvocationHandler implements InvocationHandler { private final MBeanServerConnection conn; private Map<ObjectName, NameValueMap> cachedValues = newMap(); private Map<ObjectName, Set<String>> cachedNames = newMap(); @SuppressWarnings("serial") private static final class NameValueMap extends HashMap<String, Object> {} 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();