|
import java.io.*; |
|
import java.util.*; |
|
import java.util.stream.*; |
|
import java.lang.reflect.*; |
|
import javax.management.*; |
|
|
|
import sun.tools.jconsole.*; |
|
|
|
|
|
public class JMXClient implements AutoCloseable{ |
|
|
|
private ProxyClient client; |
|
|
|
private JMXClient(ProxyClient client){ |
|
this.client = client; |
|
} |
|
|
|
@Override |
|
public void close() throws Exception{ |
|
Optional.ofNullable(client) |
|
.ifPresent(c -> c.disconnect()); |
|
} |
|
|
|
public static void listLocalVMs(){ |
|
LocalVirtualMachine.getAllVirtualMachines() |
|
.forEach((k, v) -> System.out.println(k + ": " + v)); |
|
} |
|
|
|
public static JMXClient getJMXClient(int pid) |
|
throws IOException, NoSuchMethodException, |
|
IllegalAccessException, InvocationTargetException{ |
|
LocalVirtualMachine vm = LocalVirtualMachine.getLocalVirtualMachine(pid); |
|
if(vm == null){ |
|
throw new RuntimeException(pid + " is not accessible!"); |
|
} |
|
|
|
ProxyClient client = ProxyClient.getProxyClient(vm); |
|
|
|
Method connectMethod = ProxyClient.class.getDeclaredMethod( |
|
"connect", boolean.class); |
|
connectMethod.setAccessible(true); |
|
connectMethod.invoke(client, false); |
|
|
|
return new JMXClient(client); |
|
} |
|
|
|
public void listMBeans() throws IOException{ |
|
client.getMBeans(null) |
|
.forEach((k, v) -> System.out.print(k + ":\n" + |
|
" " + v.getDescription() + "\n")); |
|
} |
|
|
|
private void dumpAttribute(ObjectName objectName, MBeanAttributeInfo info){ |
|
System.out.print(" "); |
|
|
|
if(info.isReadable()){ |
|
try{ |
|
System.out.println( |
|
client.getAttributes(objectName, new String[]{info.getName()}) |
|
.stream() |
|
.map(a -> a.toString()) |
|
.collect(Collectors.joining(", "))); |
|
} |
|
catch(IOException e){ |
|
throw new UncheckedIOException(e); |
|
} |
|
} |
|
else{ |
|
System.out.println(info.getName()); |
|
} |
|
|
|
} |
|
|
|
private void dumpOperation(MBeanOperationInfo info){ |
|
System.out.print(" " + info.getReturnType() + |
|
" " + info.getName() + |
|
" ("); |
|
System.out.print(Arrays.stream(info.getSignature()) |
|
.map(p -> p.getType() + " " + p.getName()) |
|
.collect(Collectors.joining(", "))); |
|
System.out.println(")"); |
|
} |
|
|
|
private void dumpNotification(MBeanNotificationInfo info){ |
|
System.out.println(" " + info.getName()); |
|
System.out.println(" " + |
|
Arrays.stream(info.getNotifTypes()) |
|
.collect(Collectors.joining(", "))); |
|
} |
|
|
|
public void dumpMBean(String name) throws IOException, |
|
MalformedObjectNameException{ |
|
ObjectName objectName = new ObjectName(name); |
|
MBeanInfo mbeanInfo = client.getMBeans(null) |
|
.get(objectName); |
|
if(mbeanInfo == null){ |
|
throw new RuntimeException(objectName + " not found"); |
|
} |
|
|
|
System.out.println(objectName.toString()); |
|
System.out.println(" " + mbeanInfo.getDescription()); |
|
|
|
System.out.println(); |
|
System.out.println("Attributes:"); |
|
Arrays.stream(mbeanInfo.getAttributes()) |
|
.forEach(a -> dumpAttribute(objectName, a)); |
|
|
|
System.out.println(); |
|
System.out.println("Operations:"); |
|
Arrays.stream(mbeanInfo.getOperations()) |
|
.forEach(o -> dumpOperation(o)); |
|
|
|
System.out.println(); |
|
System.out.println("Notifications:"); |
|
Arrays.stream(mbeanInfo.getNotifications()) |
|
.forEach(n -> dumpNotification(n)); |
|
} |
|
|
|
public void invoke(String name, String operationName, |
|
Object[] params, String[] signature) |
|
throws IOException, MalformedObjectNameException, MBeanException{ |
|
System.out.println(client.invoke(new ObjectName(name), |
|
operationName, params, signature)); |
|
} |
|
|
|
public static void main(String[] args) throws Exception{ |
|
|
|
if(args.length == 0){ |
|
listLocalVMs(); |
|
return; |
|
} |
|
|
|
try(JMXClient jmxClient = JMXClient.getJMXClient( |
|
Integer.parseInt(args[1]))){ |
|
|
|
switch(args[0]){ |
|
|
|
case "-l": |
|
jmxClient.listMBeans(); |
|
break; |
|
|
|
case "-d": |
|
jmxClient.dumpMBean(args[2]); |
|
break; |
|
|
|
case "-c": // call void operation |
|
jmxClient.invoke(args[2], args[3], new Object[0], new String[0]); |
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
} |