dev2dev 首页 > 资源中心 > 专家Blog > 专家Blog文章
JRCMD走得更远
长时间以来,JRockit就一直可以在启动后使用ctrl-break/kill -3信号处理程序以一种非常简洁的方式与JVM交互。只需将一个名为ctrlhandler.act的文件放到当前工作目录下,按下ctrl-break(Windows下),然后文件就会被分析,文件中的命令就会被执行。更多信息请参见我的文章:轻松玩转JROCKIT 5.0——轻松玩转JVM。
我们介绍了一种使用JRCMD命令行工具的更简单的方法,该工具可以用于在本地机器上列出所有的性能计数器,或者在JRockit进程上运行ctrl-break处理程序。
下面的例子是perfcounter例子(请参见我以前的一篇文章)的扩展版本,它也像JRCMD一样,允许读取/执行性能计数器和ctrl-break处理程序——但是是从另一台机器上远程进行!
import java.lang.management.ManagementFactory;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.management.Attribute;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
/**
* Simple code example on how to execute ctrl-break handlers remotely.
*
* Usage: RemoteJRCMD -host <host> -port <host> -user <user>
* -pass <password> -command <command> [<params>]
*
* All arguments are optional. If no command is specified, all performance
* counters and their current values are listed.
*
* @author Marcus Hirt
*/
public class RemoteJRCMD
{
private final static String KEY_CREDENTIALS =
"jmx.remote.credentials";
private final static String JROCKIT_PERFCOUNTER_MBEAN_NAME =
"com.jrockit:type=JRockitPerfCounters";
private final static String JROCKIT_CONSOLE_MBEAN_NAME =
"com.jrockit:type=JRockitConsole";
private final static String[] SIGNATURE =
new String[] { "java.lang.String" };
public static void main(String[] args) throws Exception
{
HashMap commandMap = new HashMap();
commandMap.put("-host", "localhost");
commandMap.put("-port", "7091");
for (int i = 0; i < args.length; i++)
{
if (args[i].startsWith("-"))
{
StringBuilder buf = new StringBuilder();
int j = i + 1;
while (j < args.length && !args[j].startsWith("-"))
{
buf.append(" ");
buf.append(args[j++]);
}
commandMap.put(args[i], buf.toString().trim());
i = j - 1;
}
}
executeCommand(commandMap.get("-host"), Integer.parseInt(commandMap
.get("-port")), commandMap.get("-user"), commandMap
.get("-password"), commandMap.get("-command"));
}
public static void executeCommand(String host, int port, String user,
String password, String command) throws Exception
{
MBeanServerConnection server = null;
JMXConnector jmxc = null;
Map map = null;
if (user != null || password != null)
{
map = new HashMap();
final String[] credentials = new String[2];
credentials[0] = user;
credentials[1] = password;
map.put(KEY_CREDENTIALS, credentials);
}
// Use same convention as Sun. localhost:0 means "VM, monitor thyself!"
if (host.equals("localhost") && port == 0)
{
server = ManagementFactory.getPlatformMBeanServer();
}
else
{
jmxc = JMXConnectorFactory.newJMXConnector(createConnectionURL(
host, port), map);
jmxc.connect();
server = jmxc.getMBeanServerConnection();
}
System.out.println("Connected to " + host + ":" + port);
if (command == null)
{
ObjectName perfCounterObjectName = new ObjectName(
JROCKIT_PERFCOUNTER_MBEAN_NAME);
System.out.println("Listing all counters...");
MBeanAttributeInfo[] attributes = server.getMBeanInfo(
perfCounterObjectName).getAttributes();
System.out.println("Counter\tValue\n=======\t====");
String[] attributeNames = new String[attributes.length];
for (int i = 0; i < attributes.length; i++)
{
attributeNames[i] = attributes[i].getName();
}
Iterator valueIter = server.getAttributes(perfCounterObjectName,
attributeNames).iterator();
while (valueIter.hasNext())
{
Attribute attr = (Attribute) valueIter.next();
System.out.println(attr.getName() + "\t=\t" + attr.getValue());
}
}
else
{
System.out.println("Invoking the ctrl-break command '" + command
+ "'...");
ObjectName consoleObjectName = new ObjectName(
JROCKIT_CONSOLE_MBEAN_NAME);
Object[] params = new Object[1];
params[0] = command;
System.out
.println("The CtrlBreakCommand returned: \n"
+ server.invoke(consoleObjectName,
"runCtrlBreakHandlerWithResult", params,
SIGNATURE));
}
if (jmxc != null)
{
jmxc.close();
}
}
private static JMXServiceURL createConnectionURL(String host, int port)
throws MalformedURLException
{
return new JMXServiceURL("rmi", "", 0, "/jndi/rmi://" + host + ":"
+ port + "/jmxrmi");
}
}
下面的例子将在localhost(默认端口7091)上列出所有的性能计数器及其值:
java RemoteJRCMD
下面的例子将在一个运行在主机bitsy、端口7091上的JRockit上启动一个60秒的JRA记录,并将生成的记录写入一个名为nisse.zip的文件中:
java RemoteJRCMD -command jrarecording filename=nisse time=60 -host bitsy -port 7091
与往常一样,不要忘了启用希望监控的JRockit的JMX管理代理。
原文出处:http://dev2dev.bea.com/blog/hirt/archive/2005/12/jrcmd_goes_remo.html
作者其它文章
|