java JMX实践:JMX RMI Server 和Client的使用

背景

最近接到一个需求,通过java的方式实现JVM进程jstack信息的采集。

考虑到java 调用linux shell 的实现方式不够优雅

1、有外部的shell 命令调用,无法严格限制资源的使用

2、只能采集本机JVM的信息,无法进行远程信息的调用

正好我们的JVM服务启动了JMX的远程连接配置,因此决定通过JMX RMI的协议,远程调用ThreadMXBean的dumpAllThreads 方法,来实现jstack的信息采集。

JMX的了解 可自行百度,博主理解就是一种对JVM进行远程调用、监控的框架。

JMX Server 的使用

JMX Server 的使用有2中方式:

    1、 使用JVM自带的功能通过参数配置开启JMX Server

    2、java 代码中自行构造Server,并启动

第一种方式

在jvm 的启动参数增加如下配置:

-Dcom.sun.management.jmxremote=true

-Djava.rmi.server.hostname=127.0.0.1

-Dcom.sun.management.jmxremote.port=50013

-Dcom.sun.management.jmxremote.authenticate=false

-Dcom.sun.management.jmxremote.ssl=false

启动时JVM 会自动启动JMXRMI 的server,供客户端进行连接

第二种方式

参考 代码 simplejmx/JmxServer.java at master · j256/simplejmx · GitHub

import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class JMXServerTest {
	private Registry registry;
	private JMXConnectorServer jmxConnectorServer;
	private int port;

	public JMXServerTest(int port) {
		this.port = port;
	}

	public void start() throws IOException {
		if (null == registry && null == jmxConnectorServer) {
			registry = LocateRegistry.createRegistry(port);
			String serverURL = "service:jmx:rmi://localhost:" + port + "/jndi/rmi://localhost:" + port + "/jmxrmi";
			JMXServiceURL jmxServiceURL = new JMXServiceURL(serverURL);
			jmxConnectorServer = JMXConnectorServerFactory.newJMXConnectorServer(jmxServiceURL, null, ManagementFactory.getPlatformMBeanServer());
			jmxConnectorServer.start();
		}
	}

	public void stop() throws IOException {
		if (null != registry && null != jmxConnectorServer) {
			jmxConnectorServer.stop();
			UnicastRemoteObject.unexportObject((Remote) jmxConnectorServer, true);
		}
	}

	public static void main(String[] args) throws IOException, InterruptedException {
		JMXServerTest server = new JMXServerTest(4444);
		server.start();
		Thread.sleep(60000000);
	}
}

JMX Client 的使用

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.MBeanException;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.openmbean.CompositeData;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import java.io.IOException;
import java.lang.management.ThreadInfo;
import java.util.HashMap;
import java.util.Map;

public class JMXClientTest {
	public static void main(String[] args) throws IOException, MalformedObjectNameException, ReflectionException, InstanceNotFoundException, IntrospectionException, AttributeNotFoundException, MBeanException {
		int port = 4444;
		String host = "localhost";
		JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi");
		Map<String, Object> env = new HashMap<String, Object>();
		JMXConnector jmxc = JMXConnectorFactory.connect(url, env);
		MBeanServerConnection beanConn = jmxc.getMBeanServerConnection();
		getThreadsStacks(beanConn);
	}

	public static void getThreadsStacks(MBeanServerConnection beanConn) throws MalformedObjectNameException, ReflectionException, InstanceNotFoundException, MBeanException, IOException {
		StringBuilder sb = new StringBuilder();
		CompositeData[] datas= (CompositeData[]) beanConn.invoke(
				new ObjectName("java.lang:type=Threading"),
				"dumpAllThreads",
				new Object[]{false, false}, new String[]{boolean.class.getName(), boolean.class.getName()});
		for (CompositeData data : datas) {
			ThreadInfo info = ThreadInfo.from(data);
			sb.append(info);

		}
		System.out.println(sb);
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值