????????JMX架構由三個主要組件構成:
- ?MBeans(Managed Beans)?:代表可管理的資源,是JMX的核心。MBean可以是Java類或接口,提供了管理操作的接口,如獲取系統信息、設置參數等。
- ?MBeanServer?:運行MBeans并處理管理操作的實體。每個Java虛擬機(JVM)都默認包含一個MBeanServer,它可以注冊和管理MBeans,并提供了一組API來注冊、查詢、調用MBean的方法以及接收MBean的通知。
- ?代理(Agents)?:用于暴露MBeanServer給網絡中的其他管理工具或系統。JMX代理是一個獨立的Java程序,負責加載和管理MBean。
MBean
- MBean 是JMX中的一個標準概念,它代表了一個可以被管理的資源。
- MBean 必須遵循特定的接口規范,比如它必須實現一個特定的接口或者繼承自?
javax.management.DynamicMBean
。 - MBean 可以是標準的(Standard MBean)、動態的(Dynamic MBean)、開放式的(Open MBean)或者模型式的(Model MBean)。
- MBean 的方法名稱和簽名必須與它們公開的屬性和操作完全匹配。
MBean 分類
?JMX標準中將MBean分為以下幾種:
- Standard MBean(標準 MBean):它是最簡單的一種 MBean 類型。一個標準 MBean 由一個 Java 接口和一個對應的實現類組成。接口中定義了 MBean 的屬性和操作,實現類則提供了對應的實現。標準 MBean 的命名約定為 YourInterfaceNameMBean。
- Dynamic MBean(動態 MBean):與標準 MBean 不同,動態 MBean 可以在運行時動態地確定其屬性和操作。動態 MBean 的屬性和操作是在運行時通過方法調用來確定的,因此可以根據需要進行動態修改。
-
Model MBean(模型 MBean):模型 MBean 是一種特殊的 MBean,它通過描述符來描述其管理接口,可以在運行時動態地配置其屬性和操作。模型 MBean 可以通過 XML 或者通過程序動態地加載描述符。
- Open MBean:開放 MBean 是一種通用的 MBean 類型,它可以包含各種類型的屬性和操作。開放 MBean 不限制其屬性和操作的類型,因此可以包含任意類型的數據。
-
MXBean:MXBean 是一種專門用于 JMX 的 MBean 類型。它定義了一種簡單的 Java 接口和實現約定,用于描述 MBean 的屬性和操作,同時這些接口和實現類遵循 Java Bean 的命名約定。MXBean 在 JMX 中用于管理特定類型的對象,例如內存使用情況、線程信息等。
?Standard MBean
????????Standard MBean按照JMX的命名規范來定義接口然后注冊到MBean?Server中,MBean就能被JMX的client端訪問到。
public interface HelloMBean {String getName();void setName(String name);void sayHello();
}public class Hello implements HelloMBean {private String name;
?@Overridepublic String getName() {return name;}
?@Overridepublic void setName(String name) {this.name = name;}
?@Overridepublic void sayHello() {System.out.println("Hello, " + name + "!");}
}
?public class Main {public static void main(String[] args) throws Exception {// 創建標準 MBean 實例HelloMBean helloMBean = new Hello();// 創建 MBeanServerMBeanServer mbs = ManagementFactory.getPlatformMBeanServer();// 創建 ObjectName,用于標識 MBeanObjectName name = new ObjectName("com.example:type=Hello");// 注冊 MBean 到 MBeanServermbs.registerMBean(helloMBean, name);// 等待一段時間,使得可以通過 JConsole 或者其他 JMX 客戶端來操作 MBeanThread.sleep(Long.MAX_VALUE);}
}
Spring boot 實現方式
1. 引入依賴
<!-- Spring Boot Actuator 依賴,它包含了 JMX 的支持 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId> </dependency>
2. yml 配置
spring:jmx:enabled: true
3. 注解實現Mbean 類
@Component
@ManagedResource(objectName = "bean:name=myBeanTest", description = "My Managed Bean")
public class MbeanTest {private String name;@ManagedAttribute(description = "The Name")public String getName() {return name;}@ManagedAttribute(description = "The Name")public void setName(String name) {this.name = name;}@ManagedOperation(description = "Say Hello")public String sayHello() {return "Hello, " + name;}
}
Dynamic MBean
????????動態 MBean 的核心是實現 DynamicMBean 接口,該接口定義了一組方法,用于動態地獲取和設置 MBean 的屬性,執行 MBean 的操作,以及獲取 MBean 的元數據信息。以下是 DynamicMBean 接口的幾個核心方法:
- getAttribute(String attribute):根據屬性名獲取屬性值。
- setAttribute(Attribute attribute):設置指定屬性的值。
- getAttributes(String[] attributes):批量獲取屬性值。
- setAttributes(AttributeList attributes):批量設置屬性值。
- invoke(String actionName, Object[] params, String[] signature):執行指定的操作。
- getMBeanInfo():獲取 MBean 的元數據信息,包括屬性、操作和描述信息。
@Component
@ManagedResource(objectName = "bean:name=DynamicMBeanTest", description = "My Dynamic Bean")
public class DynamicMBeanTest implements DynamicMBean {private String name;@Overridepublic Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException {if (attribute.equals("Name")) {return name;} else {throw new AttributeNotFoundException("Attribute '" + attribute + "' not found");}}@Overridepublic void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {if (attribute.getName().equals("Name")) {name = (String) attribute.getValue();} else {throw new AttributeNotFoundException("Attribute '" + attribute.getName() + "' not found");}}@Overridepublic AttributeList getAttributes(String[] attributes) {AttributeList attrs = new AttributeList();for (String attr : attributes) {try {Object value = getAttribute(attr);attrs.add(new Attribute(attr, value));} catch (Exception e) {// Ignore if attribute not found}}return attrs;}@Overridepublic AttributeList setAttributes(AttributeList attributes) {AttributeList responseAttrs = new AttributeList();for (Attribute attr : attributes.asList()) {try {setAttribute(attr);responseAttrs.add(new Attribute(attr.getName(), getAttribute(attr.getName())));} catch (Exception e) {// Ignore if attribute not found or set failed}}return responseAttrs;}@Overridepublic Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {if (actionName.equals("sayHello")) {return "Hello, " + name + "!";} else {throw new UnsupportedOperationException("Operation '" + actionName + "' not supported");}}@Overridepublic MBeanInfo getMBeanInfo() {MBeanAttributeInfo[] attributes = new MBeanAttributeInfo[]{new MBeanAttributeInfo("Name", "java.lang.String", "Name of the person", true, true, false)};MBeanOperationInfo[] operations = new MBeanOperationInfo[]{new MBeanOperationInfo("sayHello", "Say hello to the person", null, "java.lang.String", MBeanOperationInfo.ACTION)};return new MBeanInfo(this.getClass().getName(), "Dynamic Hello MBean", attributes, null, operations, null);}
}
Model MBean
????????Model MBean 的核心是實現?ModelMBean
?接口,該接口繼承自?DynamicMBean
?接口,因此具有動態 MBean 的所有特性,同時還添加了一些額外的方法用于管理描述符。
- setModelMBeanInfo(ModelMBeanInfo mbi):設置 Model MBean 的元數據信息,包括屬性、操作和描述符。
- setManagedResource(Object mr, String mr_type):指定 Model MBean 管理的資源對象及其類型。
public class ModelMBeanTest {private static ModelMBeanInfo createModelMBeanInfo() throws Exception {// 創建屬性描述符Descriptor nameDesc = new DescriptorSupport();nameDesc.setField("name", "Name");nameDesc.setField("descriptorType", "attribute");// 創建操作描述符Descriptor sayHelloDesc = new DescriptorSupport();sayHelloDesc.setField("name", "sayHello");sayHelloDesc.setField("descriptorType", "operation");// 創建屬性列表ModelMBeanAttributeInfo[] attributes = new ModelMBeanAttributeInfo[]{new ModelMBeanAttributeInfo("Name", "java.lang.String", "Name of the person", true, true, false, nameDesc)};// 創建操作列表ModelMBeanOperationInfo[] operations = new ModelMBeanOperationInfo[]{new ModelMBeanOperationInfo("sayHello", "Say hello to the person", null, "java.lang.String", MBeanOperationInfo.ACTION, sayHelloDesc)};// 創建 ModelMBeanInfoModelMBeanInfo modelMBeanInfo = new ModelMBeanInfoSupport(ModelMBeanTest.class.getName(),"Simple Model MBean Example",attributes,null,operations,null);return modelMBeanInfo;}private static ModelMBean createModelMBean(ModelMBeanInfo modelMBeanInfo) throws Exception {// 創建 ModelMBean 實例RequiredModelMBean modelMBean = new RequiredModelMBean();modelMBean.setModelMBeanInfo(modelMBeanInfo);// 創建 MBean 實例ObjectName name = new ObjectName("com.example:type=SimpleModelMBean");ModelMBeanTest example = new ModelMBeanTest();// 設置 MBean 實例modelMBean.setManagedResource(example, "ObjectReference");return modelMBean;}public static void main(String[] args) throws Exception {// 創建 ModelMBeanInfo 對象ModelMBeanInfo modelMBeanInfo = createModelMBeanInfo();// 創建 ModelMBean 實例ModelMBean modelMBean = createModelMBean(modelMBeanInfo);// 創建 MBeanServerMBeanServer mbs = ManagementFactory.getPlatformMBeanServer();// 創建 ObjectName,用于標識 MBeanObjectName name = new ObjectName("com.example:type=ModelMBeanTest");// 注冊 ModelMBean 到 MBeanServermbs.registerMBean(modelMBean, name);// 等待一段時間,使得可以通過 JConsole 或者其他 JMX 客戶端來操作 MBeanThread.sleep(Long.MAX_VALUE);}}
Open MBean
????????與傳統的 Standard MBean 和 Dynamic MBean 不同,Open MBean 不需要預先定義接口,而是使用開放式的數據類型和操作來描述 MBean 的管理接口,使得可以更靈活地適應各種場景和需求。
@Component
public class SimpleOpenMBean extends NotificationBroadcasterSupport {// Constructorpublic SimpleOpenMBean() {super();openMBean();}// The actual value of the "SimpleProperty" attributeprivate int simpleProperty = 0;// Operation to reset the SimplePropertypublic void reset() {simpleProperty = 0;}public MBeanInfo openMBean() {OpenMBeanAttributeInfoSupport simplePropertyInfo =new OpenMBeanAttributeInfoSupport("SimpleProperty","The SimpleProperty of the SimpleOpenMBean",SimpleType.INTEGER,true, // isReadabletrue, // isWritablefalse); // isIsOpenMBeanConstructorInfoSupport constructorInfo =new OpenMBeanConstructorInfoSupport("SimpleOpenMBean","Constructs a SimpleOpenMBean instance",new OpenMBeanParameterInfoSupport[]{});OpenMBeanOperationInfoSupport resetOperationInfo =new OpenMBeanOperationInfoSupport("reset","Resets the SimpleProperty to 0",new OpenMBeanParameterInfoSupport[]{},SimpleType.VOID,MBeanOperationInfo.ACTION);return new OpenMBeanInfoSupport(SimpleOpenMBean.class.getName(),"SimpleOpenMBean Description",new OpenMBeanAttributeInfo[]{simplePropertyInfo},new OpenMBeanConstructorInfo[]{constructorInfo},new OpenMBeanOperationInfo[]{resetOperationInfo},new MBeanNotificationInfo[0]);}}
MXBean? ?
????????在 Java 中,一切都被視為對象,而 JMX 則提供了一種標準化的方式來監控和管理 Java 程序的運行時狀態、性能指標以及運行環境。而MXBean就是專門用于管理和監控這其中一些標準化類型的對象的,例如內存使用情況、線程信息、操作系統屬性等。這些MBean是拿來即用的。
平臺MXBean
???????平臺MXBean是 Java SE 平臺提供的一組 MXBean,用于監視和管理 Java VM 以及 Java 運行時環境 (JRE) 的其他組件。每個平臺 MXBean 都封裝了一部分 Java VM 功能,例如類加載系統、即時 (JIT) 編譯系統、垃圾收集器等。可以使用符合 JMX 規范的監視和管理工具顯示這些 MXBean 并與之交互,以便您監視和管理這些不同的 VM 功能。Java SE 平臺的 JConsole 圖形用戶界面 (GUI) 就是這樣一種監視和管理工具。Java SE 平臺提供了一個標準平臺 MBean 服務器,這些平臺 MXBean 都注冊在該服務器中。平臺 MBean 服務器還可以注冊您希望創建的任何其他 MBean。
public class XMBeanTest {public static void main(String[] args) {// 獲取內存管理MXBean,用于監控和管理Java虛擬機的內存系統MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();// 獲取線程系統MXBean,用于監控和管理Java虛擬機的線程系統ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();// 獲取運行時系統MXBean,用于獲取Java虛擬機的運行時信息RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();// 獲取操作系統MXBean,用于獲取操作系統的相關信息OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();// 獲取編譯系統MXBean,用于獲取Java虛擬機的即時編譯器信息CompilationMXBean compilationMXBean = ManagementFactory.getCompilationMXBean();// 獲取Java虛擬機堆內存的使用情況MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();// 獲取Java虛擬機非堆內存的使用情況MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();// 獲取類加載系統的MXBean,用于監控和管理Java虛擬機的類加載系統ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();// 獲取所有內存池的MXBean列表,用于監控和管理Java虛擬機的內存池List<MemoryPoolMXBean> memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans();// 獲取所有內存管理器的MXBean列表,用于監控和管理Java虛擬機的內存管理器List<MemoryManagerMXBean> memoryManagerMXBeans = ManagementFactory.getMemoryManagerMXBeans();// 獲取所有垃圾收集器的MXBean列表,用于監控和管理Java虛擬機的垃圾收集器List<GarbageCollectorMXBean> garbageCollectorMXBeans = ManagementFactory.getGarbageCollectorMXBeans();System.out.println("Heap Memory Usage:");System.out.println(" Init: " + heapMemoryUsage.getInit() / (1024 * 1024) + " MB");System.out.println(" Used: " + heapMemoryUsage.getUsed() / (1024 * 1024) + " MB");System.out.println(" Committed: " + heapMemoryUsage.getCommitted() / (1024 * 1024) + " MB");System.out.println(" Max: " + heapMemoryUsage.getMax() / (1024 * 1024) + " MB");System.out.println("Non-Heap Memory Usage:");System.out.println(" Init: " + nonHeapMemoryUsage.getInit() / (1024 * 1024) + " MB");System.out.println(" Used: " + nonHeapMemoryUsage.getUsed() / (1024 * 1024) + " MB");System.out.println(" Committed: " + nonHeapMemoryUsage.getCommitted() / (1024 * 1024) + " MB");System.out.println(" Max: " + nonHeapMemoryUsage.getMax() / (1024 * 1024) + " MB");}
}
MBeanServer
? MBeanServer
?是一個Java對象,它充當JMX代理的核心。它提供了一個注冊和管理MBeans的環境。MBeans是遵循特定約定的Java對象,它們暴露了可以被管理的資源或服務。
MBeanServer作用
- 注冊和管理MBeans:
MBeanServer
?允許你注冊MBeans,并通過ObjectName來引用它們。每個MBean都有一個唯一的ObjectName,它是MBeanServer
用來識別和管理MBean的關鍵。 - 提供訪問接口:
MBeanServer
?提供了方法來訪問MBeans的屬性、調用操作、注冊和接收通知。 - 實現遠程管理:通過連接器(如JMXMP或JMXRMI),
MBeanServer
?支持遠程客戶端的連接,從而允許遠程管理和監控。 - 支持多種協議:
MBeanServer
?可以通過不同的協議(如RMI、JMS、HTTP等)暴露MBeans。
MBeanServer關鍵特性
- MBean注冊:通過調用
createMBean
或registerMBean
方法,可以將MBean注冊到MBeanServer
中。 - MBean操作:可以調用
invoke
方法來執行MBean的操作。 - 屬性訪問:可以通過
getAttribute
和setAttribute
方法來讀取和修改MBean的屬性。 - 事件和通知:
MBeanServer
?支持事件和通知機制,允許MBeans在特定事件發生時發送通知。 - 代理和委托:
MBeanServer
?可以作為其他MBeanServer的代理或委托,實現更復雜的管理結構。
MBeanServer創建
????????在Java應用程序中,通常使用以下方式來創建MBeanServer:
MBeanServer mBeanServer = MBeanServerFactory.createMBeanServer();
????如果使用JMX的javax.management.MBeanServerFactory
類
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
? ManagementFactory.getPlatformMBeanServer()
?方法返回的MBeanServer
?是Java虛擬機啟動時創建的平臺MBeanServer。
MBeanServer使用
????????以下是一些使用MBeanServer
的基本步驟:
- 創建或獲取
MBeanServer
實例。 - 創建MBean實例。
- 通過
ObjectName
注冊MBean到MBeanServer
。 - 使用
MBeanServer
的方法來訪問MBean的屬性、調用操作或接收通知。
// 創建MBeanServer
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();// 創建ObjectName
ObjectName name = new ObjectName("com.example:type=MyMBean");// 創建MBean實例
MyMBean mbean = new MyMBeanImpl();// 注冊MBean
mBeanServer.registerMBean(mbean, name);// 調用MBean操作
mBeanServer.invoke(name, "myOperation", new Object[]{}, new String[]{});// 讀取MBean屬性
Integer value = (Integer) mBeanServer.getAttribute(name, "MyAttribute");
JMX Agent
????????JMX Agent是指一個運行在Java虛擬機(JVM)中的管理實體,它負責管理一個或多個MBeans(Managed Beans),并提供與外部管理應用程序(如JMX客戶端)的通信接口。
JMX Agent的組成
????????一個JMX?agent
?通常包含以下幾個主要組件:
-
MBeanServer:
agent
?的核心組件,負責注冊和管理MBeans,并提供對MBeans的操作、屬性訪問和通知的接口。 -
MBeans:實現具體管理功能的Java對象,它們可以是標準MBeans、動態MBeans、開放MBeans或模型MBeans。
-
JMX Connector:允許遠程管理應用程序通過特定的協議(如RMI、JMXMP、IIOP、HTTP等)連接到
agent
。 -
Service MBean:提供
agent
級別的服務,如安全管理、事件處理、監控服務等。 -
Adaptor:將
agent
中的MBeans暴露給不同的管理協議,例如將MBeans通過JMX RMI連接器暴露給遠程客戶端。
JMX Agent的功能
- 本地和遠程管理:
agent
?支持本地和遠程管理,使得管理員可以通過本地或遠程JMX客戶端對Java應用程序進行監控和管理。 - 服務封裝:
agent
?可以將Java應用程序中的服務封裝成MBeans,從而便于管理。 - 安全管理:
agent
?可以實現訪問控制,確保只有授權的管理員可以訪問或修改MBeans。 - 事件和通知:
agent
?支持事件和通知機制,允許MBeans在特定事件發生時發送通知給感興趣的監聽者。
JMX Agent的生命周期
- 啟動:當Java應用程序啟動時,JMX?
agent
?也會啟動,并創建MBeanServer。 - 運行:在運行期間,
agent
?管理MBeans,處理來自JMX客戶端的請求,發送和接收通知。 - 關閉:當Java應用程序關閉時,
agent
?會進行清理工作,如注銷MBeans,關閉連接器等。
JMX Agent創建
????????創建一個簡單的JMX?agent
?通常涉及以下步驟:
- 創建
MBeanServer
實例。 - 創建并注冊MBeans到
MBeanServer
。 - 創建JMX連接器,以便遠程訪問。
- 啟動連接器,使
agent
?可以接受遠程連接。
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;public class JMXAgent {public static void main(String[] args) throws Exception {// 創建MBeanServerMBeanServer mBeanServer = MBeanServerFactory.createMBeanServer();// 創建ObjectNameObjectName name = new ObjectName("com.example:type=MyMBean");// 創建并注冊MBeanMyMBean mbean = new MyMBeanImpl();mBeanServer.registerMBean(mbean, name);// 創建JMX服務URLJMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi");// 創建JMXConnectorServerJMXConnectorServer connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mBeanServer);// 啟動連接器connectorServer.start();// 打印連接信息System.out.println("JMX Agent is running at: " + url);}
}
參考文獻
官方文檔 :?https://docs.oracle.com/javase/tutorial/jmx/overview/index.html
【JMX】JAVA監控的基石-CSDN博客
JMX使用詳解-CSDN博客