1065 lines · 38.5 KB · Java
RawDownload
/* * Copyright (c) 2004, 2008, 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 com.sun.tools.jconsole.JConsoleContext.ConnectionState;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 (InternalError) new InternalError(e.getMessage()).initCause(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() {        setConnectionState(ConnectionState.CONNECTING);        try {            tryConnect();            setConnectionState(ConnectionState.CONNECTED);        } catch (Exception e) {            if (JConsole.isDebug()) {                e.printStackTrace();            }            setConnectionState(ConnectionState.DISCONNECTED);        }    }     private void tryConnect() 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());                }            }            // 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();                } else {                    this.jmxc = JMXConnectorFactory.connect(jmxUrl);                }            } else {                Map<String, String[]> env = new HashMap<String, String[]>();                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 e) {            InternalError ie = new InternalError(e.getMessage());            ie.initCause(e);            throw ie;        } catch (InstanceNotFoundException e) {            InternalError ie = new InternalError(e.getMessage());            ie.initCause(e);            throw ie;        } catch (ReflectionException e) {            InternalError ie = new InternalError(e.getMessage());            ie.initCause(e);            throw ie;        }         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 + ":" +

Lines 1–500 of 1065.