JMX简介
在Java程序中,我们常常需要对JVM和系统进行检测,在以前,开发人员必须通过一些底层的 JVM API,比如 JVMPI 和 JVMTI 等,才能监测 Java 程序运行过程中的一系列情况,但是这种需要大量的 C 程序和 JNI 调用,开发效率十分低下,为了解决这个问题,Sun 公司也在其 Java SE 5 版本中,正式提出了 Java 管理扩展(Java Management Extensions,JMX)用来管理检测 Java 程序,同时 JMX 也在 J2EE 1.4 中被发布。
MBean、MBeanServer
MBean是Managed Bean的简称。在JMX中MBean代表一个被管理的资源实例,通过MBean中暴露的方法和属性,外界可以获取被管理的资源的状态和操纵MBean的行为。
MBean在一个MBeanServer中。MBeanServer管理这些MBean,并且代理外界对它们的访问。并且MBeanServer提供了一种注册机制,外界可以通过名字来得到相应的MBean实例。
创建MBean时,必须遵循一种特定的设计模式。模型MBean类必须实现一个具有以下名称的接口:“模型类名称”加MBean。
代码实例
public interface TestMBean {
public void close();
public void start();
public void change(String name);
}
public class Test implements TestMBean {
@Override
public void close() {
System.out.println("关闭");
}
@Override
public void start() {
System.out.println("打开");
}
@Override
public void change(String name) {
System.out.println("改变-------》"+name);
}
}
首先我们需要将MBean实现注册到MBean服务器,注册MBean之后,为了能够对其进行测试,需要添加一个死循环以防止应用程序终止,然后才能通过JConsole访问MBean。
ObjectName表示一个MBean的对象名称。
public class Main {
public static void main(String[] args) {
try {
ObjectName objectName = new ObjectName("com.baeldung.tutorial:type=basic,name=game");
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
server.registerMBean(new Test(), objectName);
} catch (MalformedObjectNameException | InstanceAlreadyExistsException |
MBeanRegistrationException | NotCompliantMBeanException e) {
// handle exceptions
}
for(;;){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
要启动JConsole,可以打开一个终端窗口并运行jconsole命令,这个程序在JDK_HOME/bin下。
JConsole允许创建本地连接以及与远程进程的连接,我们可以在本地进程列表中看到我们的程序名称。只需选择应用程序并单击“连接”按钮,连接后转到MBean选项卡,我们就可以动态更改的值。
客户端示例
虽然JConsole提供了图形化界面操作,但是有些地方就不太合适使用,比如我们需要定期调用MBean的某些功能,每10分钟检查一次状态。在这种情况下,我们需要自己编写一个连接到JMX MBean服务器并调用MBean操作的操作。
以下代码启动MBean服务器,端口为9696,并禁用了SSL和身份验证。
public class Main {
private static int PORT=9696;
public static void main(String[] args) {
try {
ObjectName objectName = new ObjectName("com.hxl.jmx:type=basic,name=hxl");
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
server.registerMBean(new Test(), objectName);
LocateRegistry.createRegistry(PORT);
JMXServiceURL url = new JMXServiceURL
("service:jmx:rmi:///jndi/rmi://localhost:"+PORT+"/jmxrmi");
JMXConnectorServer jcs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);
jcs.start();
} catch (Exception e) {
}
for(;;){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
上面这段还可以通过启动参数来控制,不需要编写代码,但如果同时存在的话,两个端口貌似是都可以使用。
-Dcom.sun.management.jmxremote.port=1234
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
下面是客户端,大概三步。
创建JMXServiceURL,给他传递RMI主机和端口,所有的JMX URL都必须以“service:jmx”开头,否则会抛MalformedURLException。
通过JMXConnectorFactory获取一个JMXConnector实
通过MBeanServerInvocationHandler返回TestMBean代理
public class ClientTest {
private static final String HOST="127.0.0.1";
private static int PORT=9696;
public static void main(String[] args) {
try {
JMXServiceURL url =
new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + HOST + ":" + PORT + "/jmxrmi");
//之后,我们必须使用JMXConnector工厂类来获取实例。
JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
MBeanServerConnection mbeanServerConnection = jmxConnector.getMBeanServerConnection();
ObjectName mbeanName = new ObjectName("com.hxl.jmx:type=basic,name=hxl");
//获取代理,如果获得代理成功,就可以调用MBean公开的任何操作。
TestMBean mbeanProxy =
(TestMBean) MBeanServerInvocationHandler.newProxyInstance(
mbeanServerConnection, mbeanName, TestMBean.class, true);
mbeanProxy.start();
mbeanProxy.change("test");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (MalformedObjectNameException e) {
e.printStackTrace();
}
}
}
运行之后控制台会输出如下:
Tomcat JMX
首先需要在catalina.sh中配置开启JMX,Windows为catalina.bat,以下在Linux中演示,在catalina.sh中加入以下参数即可,端口可以随意更改,但是注意需要在一行。
CATALINA_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"
通过./catalina.sh run
运行Tomcat,在JConsole中选中远程连接,输入127.0.0.1:9999进行连接。
以下演示停止、启动某个项目。
选中最右侧的MBean选项卡,接着展开WebModule。
选中某个要停止的项目后,点击"操作"-----stop(),即可停止项目。
停止后无法在访问,相反,点击start()可以重新启动。
基于这个,我们可以自己做一套Tomcat管理软件。