写在前面
本文来看先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";@Overridepublic String getName() {return "风筝";}@Overridepublic String getPassword() {return "密码不可见";}@Overridepublic String getPhone() {return "18900000000";}@Overridepublic void say() {System.out.println("Hello JMX");}@Overridepublic 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方式连接JMXConnectorServerLocateRegistry.createRegistry(8999);//URL路径的结尾可以随意指定,但如果需要用Jconsole来进行连接,则必须使用jmxrmiJMXServiceURL 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 了解不,我说:什么? 。