mirror of https://github.com/apache/activemq.git
Use the JMX VirtualMachine Management API in tools.jar to find the JMS connector URL instead of the private sun APIs. git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@1147154 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
8e61f519df
commit
2cce056eb4
|
@ -19,7 +19,6 @@ package org.apache.activemq.console.command;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
@ -27,19 +26,19 @@ import java.net.URLClassLoader;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Properties;
|
||||||
|
|
||||||
import javax.management.MBeanServerConnection;
|
import javax.management.MBeanServerConnection;
|
||||||
import javax.management.remote.JMXConnector;
|
import javax.management.remote.JMXConnector;
|
||||||
import javax.management.remote.JMXConnectorFactory;
|
import javax.management.remote.JMXConnectorFactory;
|
||||||
import javax.management.remote.JMXServiceURL;
|
import javax.management.remote.JMXServiceURL;
|
||||||
|
|
||||||
import sun.management.ConnectorAddressLink;
|
|
||||||
|
|
||||||
public abstract class AbstractJmxCommand extends AbstractCommand {
|
public abstract class AbstractJmxCommand extends AbstractCommand {
|
||||||
public static String DEFAULT_JMX_URL;
|
public static String DEFAULT_JMX_URL;
|
||||||
private static String jmxUser;
|
private static String jmxUser;
|
||||||
private static String jmxPassword;
|
private static String jmxPassword;
|
||||||
|
private static final String CONNECTOR_ADDRESS =
|
||||||
|
"com.sun.management.jmxremote.localConnectorAddress";
|
||||||
|
|
||||||
private JMXServiceURL jmxServiceUrl;
|
private JMXServiceURL jmxServiceUrl;
|
||||||
private boolean jmxUseLocal;
|
private boolean jmxUseLocal;
|
||||||
|
@ -68,58 +67,117 @@ public abstract class AbstractJmxCommand extends AbstractCommand {
|
||||||
return getJVM().equals("Sun Microsystems Inc.");
|
return getJVM().equals("Sun Microsystems Inc.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the JMX Url for a VM by its process id
|
||||||
|
*
|
||||||
|
* @param pid
|
||||||
|
* The process id value of the VM to search for.
|
||||||
|
*
|
||||||
|
* @return the JMX Url of the VM with the given pid or null if not found.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
protected String findJMXUrlByProcessId(int pid) {
|
||||||
|
|
||||||
|
if (isSunJVM()) {
|
||||||
|
try {
|
||||||
|
// Classes are all dynamically loaded, since they are specific to Sun VM
|
||||||
|
// if it fails for any reason default jmx url will be used
|
||||||
|
|
||||||
|
// tools.jar are not always included used by default class loader, so we
|
||||||
|
// will try to use custom loader that will try to load tools.jar
|
||||||
|
|
||||||
|
String javaHome = System.getProperty("java.home");
|
||||||
|
String tools = javaHome + File.separator +
|
||||||
|
".." + File.separator + "lib" + File.separator + "tools.jar";
|
||||||
|
URLClassLoader loader = new URLClassLoader(new URL[]{new File(tools).toURI().toURL()});
|
||||||
|
|
||||||
|
Class virtualMachine = Class.forName("com.sun.tools.attach.VirtualMachine", true, loader);
|
||||||
|
Class virtualMachineDescriptor = Class.forName("com.sun.tools.attach.VirtualMachineDescriptor", true, loader);
|
||||||
|
|
||||||
|
Method getVMList = virtualMachine.getMethod("list", (Class[])null);
|
||||||
|
Method attachToVM = virtualMachine.getMethod("attach", String.class);
|
||||||
|
Method getAgentProperties = virtualMachine.getMethod("getAgentProperties", (Class[])null);
|
||||||
|
Method getVMId = virtualMachineDescriptor.getMethod("id", (Class[])null);
|
||||||
|
|
||||||
|
List allVMs = (List)getVMList.invoke(null, (Object[])null);
|
||||||
|
|
||||||
|
for(Object vmInstance : allVMs) {
|
||||||
|
String id = (String)getVMId.invoke(vmInstance, (Object[])null);
|
||||||
|
if (id.equals(Integer.toString(pid))) {
|
||||||
|
|
||||||
|
Object vm = attachToVM.invoke(null, id);
|
||||||
|
|
||||||
|
Properties agentProperties = (Properties)getAgentProperties.invoke(vm, (Object[])null);
|
||||||
|
String connectorAddress = agentProperties.getProperty(CONNECTOR_ADDRESS);
|
||||||
|
|
||||||
|
if (connectorAddress != null) {
|
||||||
|
return connectorAddress;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current JMX service url being used, or create a default one if no JMX service url has been specified.
|
* Get the current JMX service url being used, or create a default one if no JMX service url has been specified.
|
||||||
* @return JMX service url
|
* @return JMX service url
|
||||||
* @throws MalformedURLException
|
* @throws MalformedURLException
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
protected JMXServiceURL useJmxServiceUrl() throws MalformedURLException {
|
protected JMXServiceURL useJmxServiceUrl() throws MalformedURLException {
|
||||||
if (getJmxServiceUrl() == null) {
|
if (getJmxServiceUrl() == null) {
|
||||||
String jmxUrl = DEFAULT_JMX_URL;
|
String jmxUrl = DEFAULT_JMX_URL;
|
||||||
int connectingPid = -1;
|
int connectingPid = -1;
|
||||||
if (isSunJVM()) {
|
if (isSunJVM()) {
|
||||||
try {
|
try {
|
||||||
// Try to attach to the local process
|
|
||||||
// Classes are all dynamically loaded, since they are specific to Sun VM
|
// Classes are all dynamically loaded, since they are specific to Sun VM
|
||||||
// if it fails for any reason default jmx url will be used
|
// if it fails for any reason default jmx url will be used
|
||||||
|
|
||||||
|
// tools.jar are not always included used by default class loader, so we
|
||||||
|
// will try to use custom loader that will try to load tools.jar
|
||||||
|
|
||||||
// tools.jar are not always included used by default
|
|
||||||
// class loader, so we will try to use custom loader that will
|
|
||||||
// try to load tools.jar
|
|
||||||
String javaHome = System.getProperty("java.home");
|
String javaHome = System.getProperty("java.home");
|
||||||
String tools = javaHome + File.separator +
|
String tools = javaHome + File.separator +
|
||||||
".." + File.separator + "lib" + File.separator + "tools.jar";
|
".." + File.separator + "lib" + File.separator + "tools.jar";
|
||||||
URLClassLoader loader = new URLClassLoader(new URL[]{new File(tools).toURI().toURL()});
|
URLClassLoader loader = new URLClassLoader(new URL[]{new File(tools).toURI().toURL()});
|
||||||
|
|
||||||
// load all classes dynamically so we can compile on non-Sun VMs
|
Class virtualMachine = Class.forName("com.sun.tools.attach.VirtualMachine", true, loader);
|
||||||
|
Class virtualMachineDescriptor = Class.forName("com.sun.tools.attach.VirtualMachineDescriptor", true, loader);
|
||||||
|
|
||||||
//MonitoredHost host = MonitoredHost.getMonitoredHost(new HostIdentifier((String)null));
|
Method getVMList = virtualMachine.getMethod("list", (Class[])null);
|
||||||
Class monitoredHostClass = Class.forName("sun.jvmstat.monitor.MonitoredHost", true, loader);
|
Method attachToVM = virtualMachine.getMethod("attach", String.class);
|
||||||
Method getMonitoredHostMethod = monitoredHostClass.getMethod("getMonitoredHost", String.class);
|
Method getAgentProperties = virtualMachine.getMethod("getAgentProperties", (Class[])null);
|
||||||
Object host = getMonitoredHostMethod.invoke(null, (String)null);
|
Method getVMDescriptor = virtualMachineDescriptor.getMethod("displayName", (Class[])null);
|
||||||
//Set vms = host.activeVms();
|
Method getVMId = virtualMachineDescriptor.getMethod("id", (Class[])null);
|
||||||
Method activeVmsMethod = host.getClass().getMethod("activeVms", null);
|
|
||||||
Set vms = (Set)activeVmsMethod.invoke(host, null);
|
List allVMs = (List)getVMList.invoke(null, (Object[])null);
|
||||||
for (Object vmid: vms) {
|
|
||||||
int pid = ((Integer) vmid).intValue();
|
for(Object vmInstance : allVMs) {
|
||||||
//MonitoredVm mvm = host.getMonitoredVm(new VmIdentifier(vmid.toString()));
|
String displayName = (String)getVMDescriptor.invoke(vmInstance, (Object[])null);
|
||||||
Class vmIdentifierClass = Class.forName("sun.jvmstat.monitor.VmIdentifier", true, loader);
|
if (displayName.contains("run.jar start")) {
|
||||||
Constructor vmIdentifierConstructor = vmIdentifierClass.getConstructor(String.class);
|
String id = (String)getVMId.invoke(vmInstance, (Object[])null);
|
||||||
Object vmIdentifier = vmIdentifierConstructor.newInstance(vmid.toString());
|
|
||||||
Method getMonitoredVmMethod = host.getClass().getMethod("getMonitoredVm", vmIdentifierClass);
|
Object vm = attachToVM.invoke(null, id);
|
||||||
Object mvm = getMonitoredVmMethod.invoke(host, vmIdentifier);
|
|
||||||
//String name = MonitoredVmUtil.commandLine(mvm);
|
Properties agentProperties = (Properties)getAgentProperties.invoke(vm, (Object[])null);
|
||||||
Class monitoredVmUtilClass = Class.forName("sun.jvmstat.monitor.MonitoredVmUtil", true, loader);
|
String connectorAddress = agentProperties.getProperty(CONNECTOR_ADDRESS);
|
||||||
Method commandLineMethod = monitoredVmUtilClass.getMethod("commandLine", Class.forName("sun.jvmstat.monitor.MonitoredVm", true, loader));
|
|
||||||
String name = (String)commandLineMethod.invoke(null, mvm);
|
if (connectorAddress != null) {
|
||||||
if (name.contains("run.jar start")) {
|
jmxUrl = connectorAddress;
|
||||||
connectingPid = pid;
|
connectingPid = Integer.parseInt(id);
|
||||||
jmxUrl = ConnectorAddressLink.importFrom(pid);
|
context.print("useJmxServiceUrl Found JMS Url: " + jmxUrl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception ignore) {}
|
}
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connectingPid != -1) {
|
if (connectingPid != -1) {
|
||||||
|
@ -163,7 +221,7 @@ public abstract class AbstractJmxCommand extends AbstractCommand {
|
||||||
* @param jmxUser - the jmx
|
* @param jmxUser - the jmx
|
||||||
*/
|
*/
|
||||||
public void setJmxUser(String jmxUser) {
|
public void setJmxUser(String jmxUser) {
|
||||||
this.jmxUser = jmxUser;
|
AbstractJmxCommand.jmxUser = jmxUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -179,7 +237,7 @@ public abstract class AbstractJmxCommand extends AbstractCommand {
|
||||||
* @param jmxPassword - the password used for JMX authentication
|
* @param jmxPassword - the password used for JMX authentication
|
||||||
*/
|
*/
|
||||||
public void setJmxPassword(String jmxPassword) {
|
public void setJmxPassword(String jmxPassword) {
|
||||||
this.jmxPassword = jmxPassword;
|
AbstractJmxCommand.jmxPassword = jmxPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -282,7 +340,7 @@ public abstract class AbstractJmxCommand extends AbstractCommand {
|
||||||
int pid = Integer.parseInt(tokens.remove(0));
|
int pid = Integer.parseInt(tokens.remove(0));
|
||||||
context.print("Connecting to pid: " + pid);
|
context.print("Connecting to pid: " + pid);
|
||||||
|
|
||||||
String jmxUrl = ConnectorAddressLink.importFrom(pid);
|
String jmxUrl = findJMXUrlByProcessId(pid);
|
||||||
// If jmx url already specified
|
// If jmx url already specified
|
||||||
if (getJmxServiceUrl() != null) {
|
if (getJmxServiceUrl() != null) {
|
||||||
context.printException(new IllegalArgumentException("JMX URL already specified."));
|
context.printException(new IllegalArgumentException("JMX URL already specified."));
|
||||||
|
|
Loading…
Reference in New Issue