什么是JMX
JMX
,全稱Java Management Extensions
,用於我們管理和監控java
應用程序。JMX
有以下用途:
- 監控應用程序的運行狀態和相關統計信息。
- 修改應用程序的配置(無需重啟)。
- 狀態變化或出錯時通知處理。
舉個例子,我們可以通過jconsole
監控應用程序的堆內存使用量、線程數、類數,查看某些配置信息,甚至可以動態地修改配置。另外,有時還可以利用JMX
來進行測試。
本文將介紹以下內容:
- 什么是
JMX
; JMX
的基礎架構;- 如何使用
JMX
。
JMX的基礎架構
首先,看下這種圖:

這里簡單介紹下這三層結構:
層次 | 描述 |
---|---|
Instrumentation | 主要包括了一系列的接口定義和描述如何開發MBean 的規范。在JMX 中MBean 代表一個被管理的資源實例,通過MBean 中暴露的方法和屬性,外界可以獲取被管理的資源的狀態和操縱MBean 的行為。 |
Agent | 用來管理相應的資源,並且為遠端用戶提供訪問的接口。該層的核心是MBeanServer ,所有的MBean 都要向它注冊,才能被管理。注冊在MBeanServer 上的MBean 並不直接和遠程應用程序進行通信,他們通過協議適配器(Adapter )和連接器(Connector )進行通信。 |
Distributed | 定義了一系列用來訪問Agent的接口和組件,包括Adapter 和Connector 的描述。注意,Adapter 和Connector 的區別在於:Adapter 是使用某種Internet 協議來與 Agent 獲得聯系,Agent 端會有一個對象 (Adapter )來處理有關協議的細節。比如SNMP Adapter 和HTTP Adapter 。而Connector 則是使用類似RPC 的方式來訪問Agent ,在Agent 端和客戶端都必須有這樣一個對象來處理相應的請求與應答。比如RMI Connector 。 |
怎么使用JMX
需求
- 測試本地連接管理
MBean
。 - 測試遠程連接管理
MBean
,包括代碼實現、啟動參數、啟動參數+配置文件等方式。 - 如何開啟賬號密碼認證。
工程環境
JDK
:1.8.0_231
maven
:3.6.1
IDE
:eclipse 4.12
主要步驟
- 定義
MBean
接口,並編寫實現類; - 注冊
MBean
到MBeanServe
; - 啟動程序;
- 使用
jconsole
連接管理該程序。
創建項目
項目類型Maven Project,打包方式jar
引入依賴
入門案例暫時不需要引入外部依賴。
編寫MBean接口
注意,接口名格式必須為:被管理的類的類名+MBean
。
public interface UserMBean {
String getName();
void setName(String name);
Integer getAge();
void setAge(Integer age);
String getAddress();
void setAddress(String address);
String sayHello();
}
編寫實現類
這里簡單實現下就行。當屬性被設置時,會在控制台打印相關內容。
public class User implements UserMBean {
private String name;
private Integer age;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
System.err.println("set name to " + name);
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
System.err.println("set age to " + age);
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
System.err.println("set address to " + address);
this.address = address;
}
public String sayHello() {
return "Hello!";
}
}
本地連接
注冊MBean
路徑為test
目錄下的cn.zzs.jmx
,類名JMXTest
。只有將MBean
注冊到MBeanServer
,MBean
才能被管理。MBean
的對象名格式為:域名:type=MBean類型,name=MBean名稱
。其中,域名
和MBean名稱
可以隨便取,對象名中除了type,我們還可以自定義其他條目,以方便管理。
注意,為了讓這個程序持續工作,這里強制線程睡眠。
public static void main(String[] args) throws Exception {
// 設置MBean對象名,格式為:“域名:type=MBean類型,name=MBean名稱”
String jmxName = "cn.zzs.jmx:type=user,name=user001";
// 獲得MBeanServer
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
// 創建ObjectName
ObjectName objectName = new ObjectName(jmxName);
// 創建並注冊MBean
server.registerMBean(new User(), objectName);
Thread.sleep(60 * 60 * 1000);
}
測試
啟動程序,打開jconsole
(在JDK
安裝路徑的bin
目錄下),出現如下界面,這時可以看到我們測試的程序:

選擇JMXTest
后,點擊連接,這時如果彈窗“安全連接失敗,是否以不安全的方式重試”,這是因為我們沒有開啟ssl
加密,可以不去理會它。點擊不安全的連接,即可進入以下頁面:

通過這個窗口我們可以查看程序的堆內存使用量、線程、類等信息,我們再點擊MBean
選項卡,可以看到我們編寫的MBean
,我們定義的對象名為cn.zzs.jmx:type=user,name=user001
,其中cn.zzs.jmx
作為第一級目錄,type=user
作為第二級目錄,name=user001
對應具體的對象,它具備屬性和操作。其中,user
的setter
和getter
方法被合並在了一起。

通過這個界面,我們可以查看和設置user
的屬性,或調用它的方法。例如,我先設置name的值,通過程序控制台可以看到該方法被調用了:

接着我再調用sayHello
方法:

通過以上例子,可以看到,JMX
還是非常有用的,除了查看類的屬性外,我們還可以在不重啟程序的情況下進行配置或執行某些方法。
以上例子中,我們只能在本地訪問JMXTest
,接下來介紹如何實現遠程連接。本文介紹三種方式,可根據實際場景選擇:
- 代碼實現;
- 啟動參數配置;
- 啟動參數+文件配置。
遠程連接方式一(代碼實現)
本例子在本地連接的基礎上修改。
開啟遠程連接
注意,這里的localhost
最好改為你的IP
,不然可能連接不上。
public static void main(String[] args) throws Exception {
// 設置MBean對象名,格式為:“域名:type=MBean類型,name=MBean名稱”
String jmxName = "cn.zzs.jmx:type=user,name=user001";
// 獲得MBeanServer
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
// 創建ObjectName
ObjectName objectName = new ObjectName(jmxName);
// 創建並注冊MBean
server.registerMBean(new User(), objectName);
// 注冊一個端口
LocateRegistry.createRegistry(9999);
// URL路徑的結尾可以隨意指定,但如果需要用Jconsole來進行連接,則必須使用jmxrmi
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi");
JMXConnectorServer jcs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);
jcs.start();
}
測試
打開jconsole
,使用遠程連接方式,輸入我們設置好的ip和端口,點擊連接即可:

遠程連接方式二(啟動參數)
本例子在本地連接的基礎上修改。在程序啟動時加入以下啟動參數,也可以實現遠程連接:
-Djava.rmi.server.hostname=<your-ip> // 你的ip
-Dcom.sun.management.jmxremote.port=9999 // 開放端口號
-Dcom.sun.management.jmxremote.local.only=false // 是否只能本地連接
-Dcom.sun.management.jmxremote.ssl=false // 是否使用ssl加密
-Dcom.sun.management.jmxremote.authenticate=false // 是否需要賬號密碼認證
可以看到,我們關閉了ssl
加密和賬號密碼認證。
遠程連接方式三(啟動參數+配置文件)
本例子在本地連接的基礎上修改。
啟動參數
在程序啟動時加入以下啟動參數,並結合配置文件,也可以實現遠程連接:
-Dcom.sun.management.config.file=D:/growUp/git_repository/jdk-extend/02-jmx-demo/src/main/resources/config/management.properties // 配置文件路徑
-Djava.rmi.server.hostname=<your-ip>
配置文件
在配置文件中配置以下參數:
# 開放端口號
com.sun.management.jmxremote.port=9999
# 是否只能本地連接
com.sun.management.jmxremote.local.only=false
# 是否使用ssl加密
com.sun.management.jmxremote.ssl=false
# 是否需要賬號密碼認證
com.sun.management.jmxremote.authenticate=false
關於management.propertie
的詳細配置,可以在$JRE/lib/management/
目錄下找到。其實,當我們在啟動參數中存在以下參數時,默認會去讀取$JRE/lib/management/management.properties
的配置文件。
# -Dcom.sun.management.jmxremote.port=<port-number>
# or -Dcom.sun.management.snmp.port=<port-number>
設置賬戶密碼
實際使用中,我們更希望采用安全加密的方式來監控程序,這個時候我們可以設置ssl加密或賬號密碼認證。ssl加密的本文暫時不擴展,這里只介紹如何設置賬號密碼認證。
啟動參數
和上個例子一樣,需要設置如下啟動參數:
-Dcom.sun.management.config.file=D:/growUp/git_repository/jdk-extend/02-jmx-demo/src/main/resources/config/management.properties
-Djava.rmi.server.hostname=<your-ip>
配置文件
配置文件中加入以下內容:
# 開放端口號
com.sun.management.jmxremote.port=9999
# 是否只能本地連接
com.sun.management.jmxremote.local.only=false
# 是否使用ssl加密
com.sun.management.jmxremote.ssl=false
# 是否需要賬號密碼認證
com.sun.management.jmxremote.authenticate=true
# 密碼文件路徑
com.sun.management.jmxremote.password.file=D:/growUp/git_repository/jdk-extend/02-jmx-demo/src/main/resources/config/jmxremote.password
# 權限文件路徑
com.sun.management.jmxremote.access.file=D:/growUp/git_repository/jdk-extend/02-jmx-demo/src/main/resources/config/jmxremote.access
在此之前,我們需要配置好密碼文件和權限文件:
密碼文件
ZhangZiSheng001 root
權限文件
ZhangZiSheng001 readwrite
測試
打開jconsole
,選擇遠程連接,並輸入賬號密碼,點擊連接即可:

參考資料
本文為原創文章,轉載請附上原文出處鏈接:https://www.cnblogs.com/ZhangZiSheng001/p/12128915.html