再構成せずに、jconsoleでリモートマシンプロセスとローカルプロセスのJMX Urlを接続する究極の方法
リモートマシン上のプロセスをjconsoleで接続しようとすると、jmxポートが構成されていないか、他の人が多いと思います.
リモートマシンのプロセスを再起動することなく、簡単な方法を説明します.
ssh -X 192.168.66.66 -l username
接続したら、jconsoleプロセスを直接実行し、本機でjconsoleのウィンドウがポップアップします.
実はこれはjconsoleでリモートマシンを接続するプロセスではなく、リモートマシン上のX出力をローカルに転送します.
プロンプトに失敗した場合は、sshを構成してXを転送することができます.
=====================================
ただし、ローカルのJavaプロセスにプログラミングで接続したい場合は、構成の再起動を変更することはできません.
たとえば、jmxで監視データを取得するプログラムがある場合は、druidのStatViewサーブレットなどのターゲットプロセスを再起動することはできません.
https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_StatViewServlet%E9%85%8D%E7%BD%AE
ローカルプロセスのjmx urlは、次の方法で得ることができます.
以前のブログ『ローカルプロセスのjmx urlを検索するコード』では、ActiveMQでローカルプロセスのjmx urlを取得する方法について言及していました.
http://blog.csdn.net/hengyunabc/article/details/8938281
この方法は時には効果がなくnullが得られるが,jconsoleでは接続できる.そこでjconsoleのソースコードを検討すると、jconsoleはターゲットプロセスの「com.sun.management.jmxremote.localConnectorAddress」環境変数値が得られない場合に、ターゲットプロセスにmanagement-agentをロードしようとする.JAr、これでjmx urlが得られます.
jconsoleの関連ソースコードOpenJDKソースコードの下のjdk/src/share/classes/sun/tools/jconsole/LOcalVirtualMachine.JAvaにあります.ここで直接見ることができます.
http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java
以下は、ローカルプロセスjmx urlを得るための改良されたコードであり、異常の処理には不十分であるが、使用には影響しない.
リモートマシンのプロセスを再起動することなく、簡単な方法を説明します.
ssh -X 192.168.66.66 -l username
接続したら、jconsoleプロセスを直接実行し、本機でjconsoleのウィンドウがポップアップします.
実はこれはjconsoleでリモートマシンを接続するプロセスではなく、リモートマシン上のX出力をローカルに転送します.
プロンプトに失敗した場合は、sshを構成してXを転送することができます.
=====================================
ただし、ローカルのJavaプロセスにプログラミングで接続したい場合は、構成の再起動を変更することはできません.
たとえば、jmxで監視データを取得するプログラムがある場合は、druidのStatViewサーブレットなどのターゲットプロセスを再起動することはできません.
https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_StatViewServlet%E9%85%8D%E7%BD%AE
ローカルプロセスのjmx urlは、次の方法で得ることができます.
以前のブログ『ローカルプロセスのjmx urlを検索するコード』では、ActiveMQでローカルプロセスのjmx urlを取得する方法について言及していました.
http://blog.csdn.net/hengyunabc/article/details/8938281
この方法は時には効果がなくnullが得られるが,jconsoleでは接続できる.そこでjconsoleのソースコードを検討すると、jconsoleはターゲットプロセスの「com.sun.management.jmxremote.localConnectorAddress」環境変数値が得られない場合に、ターゲットプロセスにmanagement-agentをロードしようとする.JAr、これでjmx urlが得られます.
jconsoleの関連ソースコードOpenJDKソースコードの下のjdk/src/share/classes/sun/tools/jconsole/LOcalVirtualMachine.JAvaにあります.ここで直接見ることができます.
http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java
以下は、ローカルプロセスjmx urlを得るための改良されたコードであり、異常の処理には不十分であるが、使用には影響しない.
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
import java.util.Properties;
public class AbstractJmxCommand {
private static final String CONNECTOR_ADDRESS =
"com.sun.management.jmxremote.localConnectorAddress";
public static String getJVM() {
return System.getProperty("java.vm.specification.vendor");
}
public static boolean isSunJVM() {
// need to check for Oracle as that is the name for Java7 onwards.
return getJVM().equals("Sun Microsystems Inc.") || getJVM().startsWith("Oracle");
}
public static void main(String[] args) {
if (args == null || args.length == 0) {
System.out.println("Usage: pid");
return;
}
int pid = Integer.parseInt(args[0]);
System.out.println(new AbstractJmxCommand().findJMXUrlByProcessId(pid));
}
/**
* 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;
}
}
}
// , agent management-agent.jar
Method getSystemProperties = virtualMachine.getMethod("getSystemProperties", (Class[])null);
Method loadAgent = virtualMachine.getMethod("loadAgent", String.class, String.class);
Method detach = virtualMachine.getMethod("detach", (Class[])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 systemProperties = (Properties)getSystemProperties.invoke(vm, (Object[])null);
String home = systemProperties.getProperty("java.home");
// Normally in ${java.home}/jre/lib/management-agent.jar but might
// be in ${java.home}/lib in build environments.
String agent = home + File.separator + "jre" + File.separator +
"lib" + File.separator + "management-agent.jar";
File f = new File(agent);
if (!f.exists()) {
agent = home + File.separator + "lib" + File.separator +
"management-agent.jar";
f = new File(agent);
if (!f.exists()) {
throw new IOException("Management agent not found");
}
}
agent = f.getCanonicalPath();
loadAgent.invoke(vm, agent, "com.sun.management.jmxremote");
Properties agentProperties = (Properties)getAgentProperties.invoke(vm, (Object[])null);
String connectorAddress = agentProperties.getProperty(CONNECTOR_ADDRESS);
//detach vm
detach.invoke(vm, (Object[])null);
if (connectorAddress != null) {
return connectorAddress;
} else {
break;
}
}
}
} catch (Exception ignore) {
System.err.println(ignore);
}
}
return null;
}
}