写在前面
本文来看先jmx相关内容。
1:jmx介绍
jvm在运行的过程中有很多的信息,比如堆内存,线程数,加载的类信息,CPU的使用量等,如果我们想要将这些信息暴漏让外界获取,该怎么做呢?此时就需要用到jmx技术了,jmx技术的全称时Java management extension,即,Java管理扩展。那么首先,Java作为面向对象的语言,自然要先将需要暴漏的信息以某种形式组织起来了,组织的形式也比较简单,就是定义bean,只不过因为其用于管理用途,所以叫做management bean,即MBean
,看似神秘,其实比较纯粹,和普通的Java bean没有任何区别,也是封装了一组属性(如可能CPU使用率属性等)
和操作(如可能执行gc的操作,以及自定义的其他方法等)
。MBean不止一个,有很多很多,为了方便MBean的管理,Java定义MbeanServer来完成MBean的统一管理工作,但是此时还不能暴漏到外界,暴漏到外界还需要用到rmi连接器,之后诸如jconsole,jvisualvm等工具就可以通过rmi连接到jvm获取各种MBean,并从中读取信息来展示,供用户进行管理和查看工作了,架构图如下:
2:自定义MBean
想要自定义MBean,我们首先需要创建接口,接口名称要以MBean结尾,如下:
public interface UserMBean {
String getName();
String getPassword();
String getPhone();
void say();
void changeUrl(String url);
}
然后我们就可以定义一个实现类作为MBean,如下:
public class User implements UserMBean {
private static String url = "https://zhuanlan.zhihu.com/p/166530442";
@Override
public String getName() {
return "风筝";
}
@Override
public String getPassword() {
return "密码不可见";
}
@Override
public String getPhone() {
return "18900000000";
}
@Override
public void say() {
System.out.println("Hello JMX");
}
@Override
public void changeUrl(String url) {
System.out.println("url值修改前为:" + User.url);
User.url = url;
System.out.println("url值修改后为:" + User.url);
}
}
定义完毕之后,还必须将MBean注册到MbeanServer中,以及设置rmi地址等,具体如下:
public class Main {
public static void main(String[] args) throws Exception {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
// ObjectName 是 MBean 的唯一标示,一个 MBeanServer 不能有重复。完整的格式「自定义命名空间:type=自定义类型,name=自定义名称」
ObjectName userName = new ObjectName("FengZheng:type=customer,name=customerUserBean");
// 注册MBean到mbeanserver中,并指定唯一名称
server.registerMBean(new User(), userName);
try {
//这个步骤很重要,注册一个端口,绑定url后用于客户端通过rmi方式连接JMXConnectorServer
LocateRegistry.createRegistry(8999);
//URL路径的结尾可以随意指定,但如果需要用Jconsole来进行连接,则必须使用jmxrmi
JMXServiceURL url = new JMXServiceURL
("service:jmx:rmi:///jndi/rmi://localhost:8999/jmxrmi");
JMXConnectorServer jcs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);
System.out.println("begin rmi start");
jcs.start();
System.out.println("rmi start");
} catch (RemoteException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Thread.sleep(60 * 60 * 1000);
}
}
这样运行之后,我们就可以通过jconsole工具中的mbean tab前看到我们自定义的MBean相关的属性信息,以及方法信息了,如下:
除了直接查看属性的值之外,还可以直接执行方法,如下执行say方法:
执行changeUrl方法,可以录入参数,如下:
当然我们也可以通过rmi来连接到jmx,实现自己的jconsole
,如下:
public class Client {
public static void main(String[] args) throws IOException, Exception, NullPointerException {
String jmxUrl = "service:jmx:rmi:///jndi/rmi://localhost:8999/jmxrmi";
monitor(jmxUrl);
}
public static void monitor(String url) throws Exception{
JMXServiceURL jmxServiceURL = new JMXServiceURL
(url);
JMXConnector jmxc = JMXConnectorFactory.connect(jmxServiceURL, null);
MBeanServerConnection msc = jmxc.getMBeanServerConnection();
String[] domains = msc.getDomains();
for (String domain : domains) {
System.out.println(domain);
}
}
}
运行如下:
JMImplementation
java.util.logging
java.lang
com.sun.management
java.nio
FengZheng
3:jdk自带MBean
jdk自带的MBean在java.lang.management包下,如下:
这些MBean都可以通过MBean的工厂类ManagementFactory获取,如下图:
我们来看下其中的RuntimeMBean,如下:
public class JdkMBeanTest {
public static void main(String[] args) {
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
System.out.println("jvm名称:" + runtimeMXBean.getName());
System.out.println("启动类加载器加载路径:" + runtimeMXBean.getBootClassPath());
System.out.println("classpath: " + runtimeMXBean.getClassPath());
System.out.println("启动时间(ms):" + runtimeMXBean.getStartTime());
System.out.println("运行时长(ms):" + runtimeMXBean.getUptime());
System.out.println("vm厂家:" + runtimeMXBean.getSpecVendor());
System.out.println("vm版本:" + runtimeMXBean.getSpecVersion());
System.out.println("系统属性:" + runtimeMXBean.getSystemProperties());
}
}
运行如下:
这些信息在jsoncole的mbean中也是可以获取的,其实获取的方式和我们是一样的如下:
通过MemoryMXBean查看堆内存:
通过ClassLoadingMXBean查看类加载和卸载信息:
通过GarbageCollectorMXBean查看GC信息:
写在后面
参考文章列表
面试官问我 JMX 了解不,我说:什么? 。