Platform MBean Server 的簡單示例

假設我們有一些伺服器註冊新使用者並用一些訊息來問候它們。我們希望監控此伺服器並更改其中的一些引數。

首先,我們需要一個與我們的監控和控制方法的介面

public interface UserCounterMBean {
    long getSleepTime();

    void setSleepTime(long sleepTime);

    int getUserCount();

    void setUserCount(int userCount);

    String getGreetingString();

    void setGreetingString(String greetingString);

    void stop();
}

一些簡單的實現將讓我們看到它是如何工作的以及我們如何影響它

public class UserCounter implements UserCounterMBean, Runnable {
    private AtomicLong sleepTime = new AtomicLong(10000);
    private AtomicInteger userCount = new AtomicInteger(0);
    private AtomicReference<String> greetingString = new AtomicReference<>("welcome");
    private AtomicBoolean interrupted = new AtomicBoolean(false);

    @Override
    public long getSleepTime() {
        return sleepTime.get();
    }

    @Override
    public void setSleepTime(long sleepTime) {
        this.sleepTime.set(sleepTime);
    }

    @Override
    public int getUserCount() {
        return userCount.get();
    }

    @Override
    public void setUserCount(int userCount) {
        this.userCount.set(userCount);
    }

    @Override
    public String getGreetingString() {
        return greetingString.get();
    }

    @Override
    public void setGreetingString(String greetingString) {
        this.greetingString.set(greetingString);
    }

    @Override
    public void stop() {
        this.interrupted.set(true);
    }

    @Override
    public void run() {
        while (!interrupted.get()) {
            try {
                System.out.printf("User %d, %s%n", userCount.incrementAndGet(), greetingString.get());
                Thread.sleep(sleepTime.get());
            } catch (InterruptedException ignored) {
            }
        }
    }
}

對於本地或遠端管理的簡單示例,我們需要註冊我們的 MBean:

import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;

public class Main {
    public static void main(String[] args) throws MalformedObjectNameException, NotCompliantMBeanException, InstanceAlreadyExistsException, MBeanRegistrationException, InterruptedException {
        final UserCounter userCounter = new UserCounter();
        final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
        final ObjectName objectName = new ObjectName("ServerManager:type=UserCounter");
        mBeanServer.registerMBean(userCounter, objectName);

        final Thread thread = new Thread(userCounter);
        thread.start();
        thread.join();
    }
}

之後我們可以執行我們的應用程式並通過 jConsole 連線到它,可以在你的 $JAVA_HOME/bin 目錄中找到它。首先,我們需要使用我們的應用程式找到我們的本地 java 程序 StackOverflow 文件

然後切換到 MBeans 選項卡,找到我們在 Main 類中用作 ObjectName 的 MBean(在上面的例子中是 ServerManager)。在 Attributes 部分,我們可以看到屬性。如果僅指定了 get 方法,則屬性將是可讀的但不可寫。如果同時指定了 get 和 set 方法,則屬性將是可讀寫的。 StackOverflow 文件

可以在 Operations 部分中呼叫指定的方法。 StackOverflow 文件

如果你希望能夠使用遠端管理,則需要其他 JVM 引數,例如:

-Dcom.sun.management.jmxremote=true //true by default
-Dcom.sun.management.jmxremote.port=36006 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false

這些引數可以在 JMX 指南的第 2 章中找到。之後,你將能夠通過 jhsole 遠端使用 jconsole host:port 或在 jConsole GUI 中指定 host:portservice:jmx:rmi:///jndi/rmi://hostName:portNum/jmxrmi 連線到你的應用程式。

有用的連結: