|
Java example source code file (ProxyClient.java)
This example Java source code file (ProxyClient.java) is included in the alvinalexander.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn
Java by Example" TM.
Learn more about this Java project at its project page.
The ProxyClient.java Java example source code
/*
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole;
import com.sun.management.HotSpotDiagnosticMXBean;
import com.sun.tools.jconsole.JConsoleContext;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.io.IOException;
import java.lang.management.*;
import static java.lang.management.ManagementFactory.*;
import java.lang.ref.WeakReference;
import java.lang.reflect.*;
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.util.*;
import javax.management.*;
import javax.management.remote.*;
import javax.management.remote.rmi.*;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.swing.event.SwingPropertyChangeSupport;
import sun.rmi.server.UnicastRef2;
import sun.rmi.transport.LiveRef;
public class ProxyClient implements JConsoleContext {
private ConnectionState connectionState = ConnectionState.DISCONNECTED;
// The SwingPropertyChangeSupport will fire events on the EDT
private SwingPropertyChangeSupport propertyChangeSupport =
new SwingPropertyChangeSupport(this, true);
private static Map<String, ProxyClient> cache =
Collections.synchronizedMap(new HashMap<String, ProxyClient>());
private volatile boolean isDead = true;
private String hostName = null;
private int port = 0;
private String userName = null;
private String password = null;
private boolean hasPlatformMXBeans = false;
private boolean hasHotSpotDiagnosticMXBean= false;
private boolean hasCompilationMXBean = false;
private boolean supportsLockUsage = false;
// REVISIT: VMPanel and other places relying using getUrl().
// set only if it's created for local monitoring
private LocalVirtualMachine lvm;
// set only if it's created from a given URL via the Advanced tab
private String advancedUrl = null;
private JMXServiceURL jmxUrl = null;
private MBeanServerConnection mbsc = null;
private SnapshotMBeanServerConnection server = null;
private JMXConnector jmxc = null;
private RMIServer stub = null;
private static final SslRMIClientSocketFactory sslRMIClientSocketFactory =
new SslRMIClientSocketFactory();
private String registryHostName = null;
private int registryPort = 0;
private boolean vmConnector = false;
private boolean sslRegistry = false;
private boolean sslStub = false;
final private String connectionName;
final private String displayName;
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 com.sun.management.OperatingSystemMXBean sunOperatingSystemMXBean = null;
private HotSpotDiagnosticMXBean hotspotDiagnosticMXBean = null;
private List<MemoryPoolProxy> memoryPoolProxies = null;
private List<GarbageCollectorMXBean> garbageCollectorMBeans = null;
final static private String HOTSPOT_DIAGNOSTIC_MXBEAN_NAME =
"com.sun.management:type=HotSpotDiagnostic";
private ProxyClient(String hostName, int port,
String userName, String password) throws IOException {
this.connectionName = getConnectionName(hostName, port, userName);
this.displayName = connectionName;
if (hostName.equals("localhost") && port == 0) {
// Monitor self
this.hostName = hostName;
this.port = port;
} else {
// Create an RMI connector client and connect it to
// the RMI connector server
final String urlPath = "/jndi/rmi://" + hostName + ":" + port +
"/jmxrmi";
JMXServiceURL url = new JMXServiceURL("rmi", "", 0, urlPath);
setParameters(url, userName, password);
vmConnector = true;
registryHostName = hostName;
registryPort = port;
checkSslConfig();
}
}
private ProxyClient(String url,
String userName, String password) throws IOException {
this.advancedUrl = url;
this.connectionName = getConnectionName(url, userName);
this.displayName = connectionName;
setParameters(new JMXServiceURL(url), userName, password);
}
private ProxyClient(LocalVirtualMachine lvm) throws IOException {
this.lvm = lvm;
this.connectionName = getConnectionName(lvm);
this.displayName = "pid: " + lvm.vmid() + " " + lvm.displayName();
}
private void setParameters(JMXServiceURL url, String userName, String password) {
this.jmxUrl = url;
this.hostName = jmxUrl.getHost();
this.port = jmxUrl.getPort();
this.userName = userName;
this.password = password;
}
private static void checkStub(Remote stub,
Class<? extends Remote> stubClass) {
// Check remote stub is from the expected class.
//
if (stub.getClass() != stubClass) {
if (!Proxy.isProxyClass(stub.getClass())) {
throw new SecurityException(
"Expecting a " + stubClass.getName() + " stub!");
} else {
InvocationHandler handler = Proxy.getInvocationHandler(stub);
if (handler.getClass() != RemoteObjectInvocationHandler.class) {
throw new SecurityException(
"Expecting a dynamic proxy instance with a " +
RemoteObjectInvocationHandler.class.getName() +
" invocation handler!");
} else {
stub = (Remote) handler;
}
}
}
// Check RemoteRef in stub is from the expected class
// "sun.rmi.server.UnicastRef2".
//
RemoteRef ref = ((RemoteObject)stub).getRef();
if (ref.getClass() != UnicastRef2.class) {
throw new SecurityException(
"Expecting a " + UnicastRef2.class.getName() +
" remote reference in stub!");
}
// Check RMIClientSocketFactory in stub is from the expected class
// "javax.rmi.ssl.SslRMIClientSocketFactory".
//
LiveRef liveRef = ((UnicastRef2)ref).getLiveRef();
RMIClientSocketFactory csf = liveRef.getClientSocketFactory();
if (csf == null || csf.getClass() != SslRMIClientSocketFactory.class) {
throw new SecurityException(
"Expecting a " + SslRMIClientSocketFactory.class.getName() +
" RMI client socket factory in stub!");
}
}
private static final String rmiServerImplStubClassName =
"javax.management.remote.rmi.RMIServerImpl_Stub";
private static final Class<? extends Remote> rmiServerImplStubClass;
static {
// FIXME: RMIServerImpl_Stub is generated at build time
// after jconsole is built. We need to investigate if
// the Makefile can be fixed to build jconsole in the
// right order. As a workaround for now, we dynamically
// load RMIServerImpl_Stub class instead of statically
// referencing it.
Class<? extends Remote> serverStubClass = null;
try {
serverStubClass = Class.forName(rmiServerImplStubClassName).asSubclass(Remote.class);
} catch (ClassNotFoundException e) {
// should never reach here
throw new InternalError(e.getMessage(), e);
}
rmiServerImplStubClass = serverStubClass;
}
private void checkSslConfig() throws IOException {
// Get the reference to the RMI Registry and lookup RMIServer stub
//
Registry registry;
try {
registry =
LocateRegistry.getRegistry(registryHostName, registryPort,
sslRMIClientSocketFactory);
try {
stub = (RMIServer) registry.lookup("jmxrmi");
} catch (NotBoundException nbe) {
throw (IOException)
new IOException(nbe.getMessage()).initCause(nbe);
}
sslRegistry = true;
} catch (IOException e) {
registry =
LocateRegistry.getRegistry(registryHostName, registryPort);
try {
stub = (RMIServer) registry.lookup("jmxrmi");
} catch (NotBoundException nbe) {
throw (IOException)
new IOException(nbe.getMessage()).initCause(nbe);
}
sslRegistry = false;
}
// Perform the checks for secure stub
//
try {
checkStub(stub, rmiServerImplStubClass);
sslStub = true;
} catch (SecurityException e) {
sslStub = false;
}
}
/**
* Returns true if the underlying RMI registry is SSL-protected.
*
* @exception UnsupportedOperationException If this {@code ProxyClient}
* does not denote a JMX connector for a JMX VM agent.
*/
public boolean isSslRmiRegistry() {
// Check for VM connector
//
if (!isVmConnector()) {
throw new UnsupportedOperationException(
"ProxyClient.isSslRmiRegistry() is only supported if this " +
"ProxyClient is a JMX connector for a JMX VM agent");
}
return sslRegistry;
}
/**
* Returns true if the retrieved RMI stub is SSL-protected.
*
* @exception UnsupportedOperationException If this {@code ProxyClient}
* does not denote a JMX connector for a JMX VM agent.
*/
public boolean isSslRmiStub() {
// Check for VM connector
//
if (!isVmConnector()) {
throw new UnsupportedOperationException(
"ProxyClient.isSslRmiStub() is only supported if this " +
"ProxyClient is a JMX connector for a JMX VM agent");
}
return sslStub;
}
/**
* Returns true if this {@code ProxyClient} denotes
* a JMX connector for a JMX VM agent.
*/
public boolean isVmConnector() {
return vmConnector;
}
private void setConnectionState(ConnectionState state) {
ConnectionState oldState = this.connectionState;
this.connectionState = state;
propertyChangeSupport.firePropertyChange(CONNECTION_STATE_PROPERTY,
oldState, state);
}
public ConnectionState getConnectionState() {
return this.connectionState;
}
void flush() {
if (server != null) {
server.flush();
}
}
void connect(boolean requireSSL) {
setConnectionState(ConnectionState.CONNECTING);
try {
tryConnect(requireSSL);
setConnectionState(ConnectionState.CONNECTED);
} catch (Exception e) {
if (JConsole.isDebug()) {
e.printStackTrace();
}
setConnectionState(ConnectionState.DISCONNECTED);
}
}
private void tryConnect(boolean requireRemoteSSL) throws IOException {
if (jmxUrl == null && "localhost".equals(hostName) && port == 0) {
// Monitor self
this.jmxc = null;
this.mbsc = ManagementFactory.getPlatformMBeanServer();
this.server = Snapshot.newSnapshot(mbsc);
} else {
// Monitor another process
if (lvm != null) {
if (!lvm.isManageable()) {
lvm.startManagementAgent();
if (!lvm.isManageable()) {
// FIXME: what to throw
throw new IOException(lvm + "not manageable");
}
}
if (this.jmxUrl == null) {
this.jmxUrl = new JMXServiceURL(lvm.connectorAddress());
}
}
Map<String, Object> env = new HashMap();
if (requireRemoteSSL) {
env.put("jmx.remote.x.check.stub", "true");
}
// Need to pass in credentials ?
if (userName == null && password == null) {
if (isVmConnector()) {
// Check for SSL config on reconnection only
if (stub == null) {
checkSslConfig();
}
this.jmxc = new RMIConnector(stub, null);
jmxc.connect(env);
} else {
this.jmxc = JMXConnectorFactory.connect(jmxUrl, env);
}
} else {
env.put(JMXConnector.CREDENTIALS,
new String[] {userName, password});
if (isVmConnector()) {
// Check for SSL config on reconnection only
if (stub == null) {
checkSslConfig();
}
this.jmxc = new RMIConnector(stub, null);
jmxc.connect(env);
} else {
this.jmxc = JMXConnectorFactory.connect(jmxUrl, env);
}
}
this.mbsc = jmxc.getMBeanServerConnection();
this.server = Snapshot.newSnapshot(mbsc);
}
this.isDead = false;
try {
ObjectName on = new ObjectName(THREAD_MXBEAN_NAME);
this.hasPlatformMXBeans = server.isRegistered(on);
this.hasHotSpotDiagnosticMXBean =
server.isRegistered(new ObjectName(HOTSPOT_DIAGNOSTIC_MXBEAN_NAME));
// check if it has 6.0 new APIs
if (this.hasPlatformMXBeans) {
MBeanOperationInfo[] mopis = server.getMBeanInfo(on).getOperations();
// look for findDeadlockedThreads operations;
for (MBeanOperationInfo op : mopis) {
if (op.getName().equals("findDeadlockedThreads")) {
this.supportsLockUsage = true;
break;
}
}
on = new ObjectName(COMPILATION_MXBEAN_NAME);
this.hasCompilationMXBean = server.isRegistered(on);
}
} catch (MalformedObjectNameException e) {
// should not reach here
throw new InternalError(e.getMessage());
} catch (IntrospectionException |
InstanceNotFoundException |
ReflectionException e) {
throw new InternalError(e.getMessage(), e);
}
if (hasPlatformMXBeans) {
// WORKAROUND for bug 5056632
// Check if the access role is correct by getting a RuntimeMXBean
getRuntimeMXBean();
}
}
/**
* Gets a proxy client for a given local virtual machine.
*/
public static ProxyClient getProxyClient(LocalVirtualMachine lvm)
throws IOException {
final String key = getCacheKey(lvm);
ProxyClient proxyClient = cache.get(key);
if (proxyClient == null) {
proxyClient = new ProxyClient(lvm);
cache.put(key, proxyClient);
}
return proxyClient;
}
public static String getConnectionName(LocalVirtualMachine lvm) {
return Integer.toString(lvm.vmid());
}
private static String getCacheKey(LocalVirtualMachine lvm) {
return Integer.toString(lvm.vmid());
}
/**
* Gets a proxy client for a given JMXServiceURL.
*/
public static ProxyClient getProxyClient(String url,
String userName, String password)
throws IOException {
final String key = getCacheKey(url, userName, password);
ProxyClient proxyClient = cache.get(key);
if (proxyClient == null) {
proxyClient = new ProxyClient(url, userName, password);
cache.put(key, proxyClient);
}
return proxyClient;
}
public static String getConnectionName(String url,
String userName) {
if (userName != null && userName.length() > 0) {
return userName + "@" + url;
} else {
return url;
}
}
private static String getCacheKey(String url,
String userName, String password) {
return (url == null ? "" : url) + ":" +
(userName == null ? "" : userName) + ":" +
(password == null ? "" : password);
}
/**
* Gets a proxy client for a given "hostname:port".
*/
public static ProxyClient getProxyClient(String hostName, int port,
String userName, String password)
throws IOException {
final String key = getCacheKey(hostName, port, userName, password);
ProxyClient proxyClient = cache.get(key);
if (proxyClient == null) {
proxyClient = new ProxyClient(hostName, port, userName, password);
cache.put(key, proxyClient);
}
return proxyClient;
}
public static String getConnectionName(String hostName, int port,
String userName) {
String name = hostName + ":" + port;
if (userName != null && userName.length() > 0) {
return userName + "@" + name;
} else {
return name;
}
}
private static String getCacheKey(String hostName, int port,
String userName, String password) {
return (hostName == null ? "" : hostName) + ":" +
port + ":" +
(userName == null ? "" : userName) + ":" +
(password == null ? "" : password);
}
public String connectionName() {
return connectionName;
}
public String getDisplayName() {
return displayName;
}
public String toString() {
if (!isConnected()) {
return Resources.format(Messages.CONNECTION_NAME__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, 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<ObjectName> mbeans = server.queryNames(name, null);
Map<ObjectName,MBeanInfo> result =
new HashMap<ObjectName,MBeanInfo>(mbeans.size());
Iterator<ObjectName> 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<ObjectName> mbeans = server.queryNames(poolName, null);
if (mbeans != null) {
memoryPoolProxies = new ArrayList<MemoryPoolProxy>();
Iterator<ObjectName> 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<ObjectName> mbeans = server.queryNames(gcName, null);
if (mbeans != null) {
garbageCollectorMBeans = new ArrayList<GarbageCollectorMXBean>();
Iterator<ObjectName> 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 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 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();
}
}
}
private Object getAttribute(ObjectName objName, String attrName)
throws MBeanException, InstanceNotFoundException,
AttributeNotFoundException, ReflectionException, IOException {
final NameValueMap values = getCachedAttributes(
objName, Collections.singleton(attrName));
Object value = values.get(attrName);
if (value != null || values.containsKey(attrName)) {
return value;
}
// Not in cache, presumably because it was omitted from the
// getAttributes result because of an exception. Following
// call will probably provoke the same exception.
return conn.getAttribute(objName, attrName);
}
private AttributeList getAttributes(
ObjectName objName, String[] attrNames) throws
InstanceNotFoundException, ReflectionException, IOException {
final NameValueMap values = getCachedAttributes(
objName,
new TreeSet<String>(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<String> attrNames) throws
InstanceNotFoundException, ReflectionException, IOException {
NameValueMap values = cachedValues.get(objName);
if (values != null && values.keySet().containsAll(attrNames)) {
return values;
}
attrNames = new TreeSet<String>(attrNames);
Set<String> 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()]));
for (Attribute attr : attrs.asList()) {
values.put(attr.getName(), attr.getValue());
}
cachedValues.put(objName, values);
cachedNames.put(objName, attrNames);
return values;
}
// See http://www.artima.com/weblogs/viewpost.jsp?thread=79394
private static <K, V> Map newMap() {
return new HashMap<K, V>();
}
}
}
Other Java examples (source code examples)
Here is a short list of links related to this Java ProxyClient.java source code file:
|