Java SE foundation consolidation (xiii): JMX

1 Overview

Many Java-related foundation books (including Java core technology I, II) are not related to the content of JMX, Java that most learners have no knowledge of JMX, but this thing is really part of Java SE, a lot of performance monitoring software is based on JMX specification development, such as jconsole.

That JMX Java Management Extensions (Java Management Extensions), is part of the Java SE, adding to the Java SE platform in Java2 time, but Java5 was officially released. JMX provides a very simple way to manage application resources, said resources here include memory resources, disk resources, and because the relevant JMX technology is dynamic, so you can monitor and manage resources in the application is running.

JMX is mainly composed of three parts:

  • Managed Beans (MBean) represents a resource, MBean can expose some of the interfaces for the resource represented by MBean view, modify, and other operations.

  • JMX agents (JMX proxy) managed by one or more MBean, MBean and exposed to the client. JMX Agent is a core component MBean Server, for accepting client connections, the client request and respond.

  • Remoete Connectors can be simply understood as a client, most close to the user, for receiving the user's request, and sends the request to the JMX agent JMX agent and then returns a response to the user.

For example, assume that the company now has a lot of food (there are many types) need to be managed, and designed a program to manage food. They are designed so that: a special kind of object to these food and set up a server that manages the food, but also developed a variety of food for a user to view the user-friendly program to purchase. In this case, the object used to represent the food is MBean, and the server is JMX Aagent, user-friendly program is actually a client.

Examples may not be appropriate, I hope you can understand the meaning of them.

Here is the JMX architecture diagram:

idoI7n.png

Next, I will focus on these three parts introduces JMX technology.

2 Managed Beans

Managed Beans referred MBean (MBean back on the uniform use of), a MBean is a Java object to be managed, and its Java Bean somewhat similar, but not exactly the same, a standard MBean includes the following:

  • Series readable or writeable or both readable and writable property.
  • A series of operations (methods) that can be invoked.
  • Describe their information.

JMX specification defines five types of MBean, namely:

  • Standard MBeans
  • Dynamic MBeans
  • Open MBeans
  • Model MBeans
  • MXBeans

This paper describes a Standard MBeans, as for other types of MBean, if readers are interested, you can find information on their own learning.

2.1 Standard MBean

The following is a "standard" MBean:

public interface HelloMBean {

    void sayHello();

    int add(int x, int y);

    String getName();

    void setCacheSize(int cacheSize);

    int getCacheSize();
}
public class Hello
        implements HelloMBean {

    private final String name = "Yeonon";

    private static final int DEFAULT_CACHE_SIZE = 200;
    private int cacheSize = DEFAULT_CACHE_SIZE;

    @Override
    public void sayHello() {
        System.out.println("hello, world!");
    }

    @Override
    public int add(int x, int y) {
        return x + y;
    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public void setCacheSize(int cacheSize) {
        int oldValue = this.cacheSize;
        this.cacheSize = cacheSize;
        System.out.println("Cache size now is : " + this.cacheSize);
    }

    @Override
    public int getCacheSize() {
        return this.cacheSize;
    }
}
复制代码

Standard MBean usually contain a suffix to MBean interface, and its implementation class, e.g. HelloMBean where the Hello class and its implementation, a set of abstract methods defined in an interface, these methods are later exposed, the main role of getter and setter methods is to represent the readability and writability of a field, if a field contains only getter methods and setter methods is not included, then the field just read, that can not pass JMX technology to modify this property. In the sample code, only defines operations that sayHello and add (getter and setter methods, although also, but do not think they are operating), the client can perform these operations in remote (calling these methods), see later a specific performance, I will not speak here.

2.2 notification

JMX also supports event notification. When MBean attributes to be modified, deleted or problems occur, they can generate a notification and send it out to, if the client contains a notification listener, the client can accept the notification and presented to the user. MBean notification mechanism to support its implementation class must implement the interface or inherit NotificationBroadcasterSupport NotificationEmitter class (recommended inherit NotificationBroadcasterSupport class, because the class has achieved a lot of useful methods), for the above Hello class to modify the code after revision follows :

public class Hello
        extends NotificationBroadcasterSupport
        implements HelloMBean {

    private final String name = "Yeonon";

    private final AtomicLong sequenceNumber = new AtomicLong(0);

    private static final int DEFAULT_CACHE_SIZE = 200;
    private int cacheSize = DEFAULT_CACHE_SIZE;

    @Override
    public void sayHello() {
        System.out.println("hello, world!");
    }

    @Override
    public int add(int x, int y) {
        return x + y;
    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public void setCacheSize(int cacheSize) {
        int oldValue = this.cacheSize;
        this.cacheSize = cacheSize;
        System.out.println("Cache size now is : " + this.cacheSize);

        Notification notification = new AttributeChangeNotification(
                this, sequenceNumber.getAndIncrement(), System.currentTimeMillis(),
                "Cache Size changed", "CacheSize", "int",
                oldValue, this.cacheSize);
        sendNotification(notification);
    }

    @Override
    public int getCacheSize() {
        return this.cacheSize;
    }

    @Override
    public MBeanNotificationInfo[] getNotificationInfo() {
        String[] types = new String[] {
                AttributeChangeNotification.ATTRIBUTE_CHANGE
        };
        String name = AttributeChangeNotification.class.getName();
        String description = "An attribute of this MBean has changed";
        MBeanNotificationInfo info = new MBeanNotificationInfo(types, name, description);
        return new MBeanNotificationInfo[]{info};
    }
}

复制代码

The main modification is generated setCacheSize method in a Notification object, an object that represents a notification Notification, Notification has already written a lot of implementation class, for example AttributeChangeNotification here, because there is reason to send notification properties are modified, so we use the implementation class, the implementation class constructor signature as follows:

    public AttributeChangeNotification(Object source, long sequenceNumber, long timeStamp, String msg,
                                       String attributeName, String attributeType, Object oldValue, Object newValue) {

        super(AttributeChangeNotification.ATTRIBUTE_CHANGE, source, sequenceNumber, timeStamp, msg);
        this.attributeName = attributeName;
        this.attributeType = attributeType;
        this.oldValue = oldValue;
        this.newValue = newValue;
    }
复制代码

A total of seven parameters, here I say a parameter (according to other parameters can know what is the parameter name), that sequenceNumber, from the parameter names may know that this is a serial number, each has a sequence of a notification, mainly to prevent the wrong order notice, and that sequence of network protocols with the same purpose. For example, if the notification transmission link between the client and the remote JMX Agent, the occurrence of the out of sequence, with the serial number, the client can know which treatment should first notification, which notifies post-treatment process to avoid out of order .

After completion notification is generated, call sendNotification () method to send notifications out. You may be in doubt? This notification is sent where to go? The answer is sent to the client there (the default is sent via RMI mechanism), if the client has realized notification listener, the client can receive and process the notification.

Let's look at JMX agent.

3 JMX Agent

JMX Agent is a core component MBean Server, can be registered in the MBean Server MBean, which means by this MBean MBean Server to manage. The following code demonstrates the MBean Server and get registered MBean MBean Server to the process of:

public class Main {

    public static void main(String[] args) throws MalformedObjectNameException, NotCompliantMBeanException, InstanceAlreadyExistsException, MBeanRegistrationException {
        MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
        ObjectName name = new ObjectName("top.yeonon.jmx:type=Hello");
        Hello mbean = new Hello();
        mBeanServer.registerMBean(mbean, name);

        System.out.println("waiting forever....");
        while (true) {

        }
    }
}

复制代码

() Can be obtained by a ManagementFactory.getPlatformMBeanServer MBean Server instance of the object, and then calls a method to put mBeanServer.registerMBean registered MBean Server MBean, the method has two parameters, one parameter is an object MBean instance, the second parameter is MBean corresponds to the name of the object is of type ObjectName name here is not necessarily that top.yeonon.jmx: type = Hello, the format is XXX: type = YYY, XXX and YYY can be any string, and not necessarily the package name and class name, but is best recommended to use the package name and class name, to avoid naming conflicts.

Start a program, find the output waiting forever ...., the program does not close, in fact, enter the infinite loop. Here the first do not worry, as long as the program does not include wrong on the line, I'll take you below some exciting!

4 JMX Client

JMX client is closest to the user, the user may not know the back of the JMX Agent, MBean, but it will know the client, the client JMX MBean and will not deal directly, but rather through its management MBean operations JMX Agent. We know Jconsole is a JMX client, the following first describes how to use Jconsole to operate MBean, followed by how to customize a JMX client.

4.1 Jconsole

Holding JMX Agent running, then open jconsole software, as follows:

id7byF.png

Select the local process corresponding to the (later will explain how to use the remote access process), then click see the following interface:

id7OeJ.png

Select the MBean tab, then find top.yeonon.jmx options here will see a name called the Hello MBean (note that you, in fact, we define that ObjectName in JMX Agent years), cacheSize now select the column, modify the value of the current value can be seen there is cacheSize 200, 150 modified, to try and click refresh, as shown below:

id7joR.png

This time back to the console, found more than one line of output:

Cache size now is : 150
复制代码

Will now cacheSize property has been changed to the 150! We successfully modify the attributes of the program is running. Other operations, such as sayHello (), add, etc., you can try on their own, this is not to say.

In addition to properties and operations, may also see a notification, select the notification the column, and then in the lower right you can see there is a "subscribe" button, click, represents want to receive notification, then try to modify CacheSize again, this time You will find many a row, as follows:

idH7tI.png

Content of the message is that we defined earlier, Jconsole just will showcase its out, and have to do too much processing.

4.2 Custom Client

Just use someone else developed a client is not mean nothing, nothing! JMX also provides a very convenient way for us to write custom clients, the following is a custom client code:

package top.yeonon.jmx;

import javax.management.*;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Set;

import static java.lang.Thread.sleep;

/**
 * @Author yeonon
 * @date 2018/10/16 0016 20:47
 **/
public class Client {

    //构建一个监听器类,该类需要实现NotificationListener接口并实现handleNotification方法
    public static class ClientListener implements NotificationListener {
        @Override
        public void handleNotification(Notification notification, Object handback) {
            echo("\nReceived notification:");
            echo("\tClassName: " + notification.getClass().getName());
            echo("\tSource: " + notification.getSource());
            echo("\tType: " + notification.getType());
            echo("\tMessage: " + notification.getMessage());
            //如果通知类型是AttributeChangeNotification,那么就获取一些和属性有关的信息
            if (notification instanceof AttributeChangeNotification) {
                AttributeChangeNotification acn = (AttributeChangeNotification) notification;
                echo("\tAttributeName: " + acn.getAttributeName());
                echo("\tAttributeType: " + acn.getAttributeType());
                echo("\tNewValue: " + acn.getNewValue());
                echo("\tOldValue: " + acn.getOldValue());
            }
        }

        public static void main(String[] args) throws IOException, MalformedObjectNameException, InstanceNotFoundException, InterruptedException {
            echo("\nCreate an RMI connector client and " +
                    "connect it to the RMI connector server");
            //构造并获取RMI连接
            JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi");
            JMXConnector jmxc = JMXConnectorFactory.connect(url, null);

            //获取MBeanServer的连接
            MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
            waitForEnterPressed();

            echo("\nMBeanServer default domain = " + mbsc.getDefaultDomain());
            echo("\nMBean count = " + mbsc.getMBeanCount());
            echo("\nQuery MBeanServer MBeans:");

            Set<ObjectName> objectNames = mbsc.queryNames(null, null);
            for (ObjectName objectName : objectNames) {
                echo("\tObjectName = " + objectName);
            }
            waitForEnterPressed();

            //创建监听器
            NotificationListener listener = new ClientListener();

            //管理 Hello MBean
            ObjectName mbeanName = new ObjectName("top.yeonon.jmx:type=Hello");
            HelloMBean mbeanProxy = JMX.newMBeanProxy(mbsc, mbeanName, HelloMBean.class, true);
            echo("\nAdd notification listener...");
            mbsc.addNotificationListener(mbeanName, listener, null, null);

            echo("\nCacheSize = " + mbeanProxy.getCacheSize());
            mbeanProxy.setCacheSize(150);
            echo("\nWaiting for notification...");
            sleep(2000);
            echo("\nCacheSize = " + mbeanProxy.getCacheSize());
            echo("\nInvoke sayHello() in Hello MBean...");
            mbeanProxy.sayHello();
            echo("\nInvoke add(2, 3) in Hello MBean...");
            mbeanProxy.add(2,3);

            waitForEnterPressed();

            //关闭客户端
            echo("\nClose the connection to the server");
            jmxc.close();
            echo("\nBye! Bye!");
        }
    }

    private static void echo(String msg) {
        System.out.println(msg);
    }

    private static void waitForEnterPressed() {
        try {
            echo("\nPress <Enter> to continue...");
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

复制代码

Code is not small, I will explain several steps to:

  1. Create a notification listener, the need to achieve and implement NotificationListener handleNotification method, the message can be processed in this method, in the demo code simply lists all the information messages to it.

  2. RMI create a connection, i.e., the following two lines of code:

    //构造一个JMXServiceURL,这里使用的是RMI的连接方式,所以要按照RMI的URL格式,端口是9999,
    JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi");
    //连接远程的JMX Agent
    JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
    复制代码
  3. Get MBeanServer connection using jmxc.getMBeanServerConnection () method to get, most operations are based on the following MBeanServer connection.

  4. If necessary, you can remove the MBeanServerConnection in a variety of information, such as the number and specific MBean MBean name (use MBeanServerConnection.queryNames).

  5. Get MBean agent you want to manage (this relates to the proxy mode). Use JMX.newMBeanProxy () method to generate an MBean brought, after MBean agent that can be used to operate a specific MBean (e.g. modified CacheSize etc.).

  6. If the reception notification, using MBeanServerConnection.addNotificationListener () method of binding a specific MBean listener.

  7. The client can use JMXConnector.close Close () method.

Before running the program, you need to run the JMX Agent program, since this is the use of RMI for remote connections, and connection port number is 9999, if the direct no argument started, then the client will not connect to the JMX Agent, you need to add parameters there are three, namely:

  • -Dcom.sun.management.jmxremote.port = 9999, that is, open interface is 9999.
  • -Dcom.sun.management.jmxremote.authenticate = false, false indicates that no user authentication.
  • -Dcom.sun.management.jmxremote.ssl = false, false representation NA SSL secure connection.

After addition of the parameters is started, the client can try to start up, the output is as follows:


Create an RMI connector client and connect it to the RMI connector server

Press <Enter> to continue...

#我按个回车

MBeanServer default domain = DefaultDomain

#远端的系统中一共有23个MBean
MBean count = 23

#23个MBean的名字
Query MBeanServer MBeans:
	ObjectName = java.lang:type=MemoryPool,name=Metaspace
	ObjectName = java.lang:type=MemoryPool,name=PS Old Gen
	ObjectName = java.lang:type=GarbageCollector,name=PS Scavenge
	ObjectName = java.lang:type=MemoryPool,name=PS Eden Space
	ObjectName = JMImplementation:type=MBeanServerDelegate
	ObjectName = java.lang:type=Runtime
	ObjectName = java.lang:type=Threading
	ObjectName = java.lang:type=OperatingSystem
	ObjectName = java.lang:type=MemoryPool,name=Code Cache
	ObjectName = java.nio:type=BufferPool,name=direct
	ObjectName = java.lang:type=Compilation
	ObjectName = top.yeonon.jmx:type=Hello
	ObjectName = java.lang:type=MemoryManager,name=CodeCacheManager
	ObjectName = java.lang:type=MemoryPool,name=Compressed Class Space
	ObjectName = java.lang:type=Memory
	ObjectName = java.nio:type=BufferPool,name=mapped
	ObjectName = java.util.logging:type=Logging
	ObjectName = java.lang:type=MemoryPool,name=PS Survivor Space
	ObjectName = java.lang:type=ClassLoading
	ObjectName = java.lang:type=MemoryManager,name=Metaspace Manager
	ObjectName = com.sun.management:type=DiagnosticCommand
	ObjectName = java.lang:type=GarbageCollector,name=PS MarkSweep
	ObjectName = com.sun.management:type=HotSpotDiagnostic

Press <Enter> to continue...

#我按个回车

Add notification listener...

CacheSize = 100

Waiting for notification...

#监听器收到了通知
Received notification:
	ClassName: javax.management.AttributeChangeNotification
	Source: top.yeonon.jmx:type=Hello
	Type: jmx.attribute.change
	Message: Cache Size changed
	AttributeName: CacheSize
	AttributeType: int
	NewValue: 150
	OldValue: 100


CacheSize = 150

#调用了sayHello()方法
Invoke sayHello() in Hello MBean...

#调用了add()方法
Invoke add(2, 3) in Hello MBean...

Press <Enter> to continue...
#回车

Close the connection to the server

Bye! Bye!
复制代码

Okay, so after knock off!

5 Summary

This paper briefly describes the three main components of the JMX, MBean, JMX Agent, Client, but only to some of the features of JMX, JMX actually far more than that, there are many more advanced features, such as extended JMX, etc., I hope this can on readers have some help.

If the article said that in some places there is a problem, correct me hope. Because I am also a beginner JMX, regarded learn while writing.

Ps: The sample code in this article are from Oracle JMX Tutorial, the following references are given in the link.

6 References

Oracle JMX Tutorial

Guess you like

Origin juejin.im/post/5d6e808e5188255878679206