Java Management Extensions (JMX)

2024-04-27 10:08
文章标签 java management jmx extensions

本文主要是介绍Java Management Extensions (JMX),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

JMX是什么

JMX是JAVA平台(JSE)标准的一部分,在J2SE 5.0中正式被加入。

JMX技术提供了一种简单,标准的方式管理注入app,设备,服务等资源,因为JMX技术是动态的,你能够用他来监控和管理资源,同时可以用来管理JM虚拟机。

JMX用java编程语言制定和定义了架构,设计模式,API以及服务来管理和监控应用程序和网络。

利用JMX,资源能够通过一个或者多个被称之为MBeans的java对象来管理和测量,这些Mbeans被注册到Mbean server上。Mbeans server攀岩了一个管理代理的角色,能够运行在大多数能够运行java语言的设备上。

在规范中定义的JMX agent由一个Mbean server(注册MBean)和一组处理MBeans的服务组成,JMX agent直接控制资源和使得他们能够远程管理应用。

JMX还定义了标准的JMX 连接器,使能够远程访问JMX agent。JMX连接器为不同的协议提供了相同的管理揭露。管理应用能够无关协议的,透明的管理资源。

 

我们为何需要JMX

l  JMX能够使得JAVA应用能够很轻量级的,付出很小代价的就能被管理起来。

l  JMX提供了标准的方式管理JAVA应用,系统,以及网络。

l  JMX能够独立于JVM之外对其进行管理

l  JMX提供了可伸缩的,动态的管理架构。

l  JMX利用已经存在的标准的服务如同JNDI以及命名服务

 

JMX的架构

 

架构

利用JMX来管理资源,首先你必须利用JAVA语言来描述和管理资源,利用MBeans来实现访问资源,MBean必须符合JMX规范中定义的借口,除了标准的Mbean以外,JMX还提供一种MXBean,。

一旦一个资源被用Mbean所描述和度量,他就能通过JMX agent 被管理起来了,Mbean在设计的时候尽量保持简单和容易被实现,此外,JMX规范还提供了通知极致,在MBeans被生成以及产生变化得时候,能够利用事件机制来进行通知。

 

JMX agent

基于代理的JMX能够通过agent直接管理资源并使得这些资源能够被远程访问并管理。一般来说,agent和他所管理的资源是在同一个机器上的,但也不一定非得如此。

Jmx agent主要由Mbean server组成,Mbean通过Mbean server进行注册,JMX agent也包括一组管理Mbean的服务,至少一个的通信的适配器或者连接器用于接受远程管理应用的访问。

 

远程管理

我们能够通过很多种不同的方式来访问JMX所管理的设备能够,比如SNMP协议等,借助之前所说的JMX 通信适配器或者连接器,Mbean server能通被agent 之外的JVM访问。

 

JVM的监控管理器

平台MXBeans是一组JavaSE 平台用于管理JVM和JRE所提供的MXBeans,美俄平台 MXBean都封装了一部分JVM的特性,如类加载系统,JIT编译系统,垃圾回收器等等,这些MXBean能够通过一些监控和管理工具显示和进行交互,使得你能够管理不同的虚拟机的特性,比如jconsole。

JavaSE 平台提供了 platform Mbean server来注册这些platform MXBean,同时,你也可以注册自定义的MBean。

 

Jconsole

JavaSE提供的监控和管理工具(GUI)

 

如何通过jconsole管理和监控一个应用

运行一个JAVA示例程序

java-Dcom.sun.management.jmxremote -jar

      jdk_home/demo/jfc/Notepad/Notepad.jar

 

-Dcom.sun.management.jmxremote开启JMX远程服务。

在运行中直接敲入jconsole,然后在本地进程列表中你能够找到Notepad.jar(本地进程,则不开启JMX远程服务依旧能找到),选择连接即可。

 

MBean

MBeans包括如下类型:

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

 

标准的Mbean

标准的Mbean需要定义名字为SomethingMBean 的接口,这个接口包括一些属性的getter/setter以及操作,标准的Mbean包括一个接口和一个实现类。接口定义了该Mbean暴露在外的属性和操作,而类则实现了这些功能和管理度量资源的操作。

 

MBean接口:

package com.example; 
 
public interface HelloMBean { 
 
    public void sayHello(); 
    public int add(int x, int y); 
    
    public String getName(); 
     
    public int getCacheSize(); 
    public void setCacheSize(int size); 
} 

 

按照约定,一个Mbean接口一般以他的实现类为前缀,如这里叫做HelloMBean,则其实现类为Hello。

 

MBean实现

package com.example; 
 
public class Hello ... 
    implements HelloMBean { 
    public void sayHello() { 
        System.out.println("hello, world"); 
    } 
     
    public int add(int x, int y) { 
        return x + y; 
    } 
     
    public String getName() { 
        return this.name; 
    }  
     
    public int getCacheSize() { 
        return this.cacheSize; 
    } 
     
    public synchronized void setCacheSize(int size) {
        ...
    
        this.cacheSize = size; 
        System.out.println("Cache size now " + this.cacheSize); 
    } 
    ...
     
    private final String name = "Reginald"; 
    private int cacheSize = DEFAULT_CACHE_SIZE; 
    private static final int 
        DEFAULT_CACHE_SIZE = 200; 
}

构造一个JMX Agent来管理资源

一旦资源能够被一个MBean来度量描述,我们需要把这些资源的管理工作在JMX Agent中执行起来。JMX Agent的核心组成部分是MBean Server,MBean Server注册的MBean的管理器。JMX Agent包括一组这样的MBean Server。

以下的Main代表了一个基本的JMX Agent。

 

package com.example; 
 
import java.lang.management.*; 
import javax.management.*; 
 
public class Main { 
 
    public static void main(String[] args) 
        throws Exception { 
     
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 
        ObjectName name = new ObjectName("com.example:type=Hello"); 
        Hello mbean = new Hello(); 
        mbs.registerMBean(mbean, name); 
          
        ...
     
        System.out.println("Waiting forever..."); 
        Thread.sleep(Long.MAX_VALUE); 
    } 
} 

 

JMX Agent开始就调用java.lang.management.ManagementFactory .getPlatformMBeanServer方法初始化了一个MBeanServer,如果这个Mbean Server被平台构造好,则会自动调用 MBeanServerFactory.createMBeanServer()来生成。

然后,JMX Agent定义了一个MBean的实例,每一个MBean都必须有一个符合JMX 规范的名字,他由一个域名和一组KEY-PROP组成,这里的域名是com.example(MBean所在的报名),KEY-PROP表示该MBean类型为Hello。然后通过 MBeanServer.registerMBean().将该MBean注册到MBean Server中。

 

执行标准MBean例子

javac com/example/*.java
 
java -Dcom.sun.management.jmxremote example.Main
 
jconsole

 

MXBeans

动态的MXBean主要还是无需MBean只引用一些预定义的数据类型。

如:

接口:

package com.example; 
 
public interface QueueSamplerMXBean { 
    public QueueSample getQueueSample(); 
    public void clearQueue(); 
} 

实现:

package com.example; 
 
import java.util.Date; 
import java.util.Queue; 
 
public class QueueSampler 
                implements QueueSamplerMXBean { 
     
    private Queue<String> queue; 
         
    public QueueSampler (Queue<String> queue) { 
        this.queue = queue; 
    } 
         
    public QueueSample getQueueSample() { 
        synchronized (queue) { 
            return new QueueSample(new Date(), 
                           queue.size(), queue.peek()); 
        } 
    } 
         
    public void clearQueue() { 
        synchronized (queue) { 
            queue.clear(); 
        } 
    } 
} 
 
package com.example; 
 
import java.beans.ConstructorProperties; 
import java.util.Date; 
 
public class QueueSample { 
     
    private final Date date; 
    private final int size; 
    private final String head; 
         
    @ConstructorProperties({"date", "size", "head"}) 
    public QueueSample(Date date, int size, 
                        String head) { 
        this.date = date; 
        this.size = size; 
        this.head = head; 
    } 
         
    public Date getDate() { 
        return date; 
    } 
         
    public int getSize() { 
        return size; 
    } 
         
    public String getHead() { 
        return head; 
    } 
}   
 

在jconsole界面上,该对象为动态对象,由一组预定义的对象组成

    private final Date date; 
    private final int size; 
    private final String head; 

在jconsole中,你能够在这个tag中看到CompositeDataSupport ,双击展开,你能够看见QueueSample 的这三个属性,是因为MXBean框架已经把对象实例转换成CompositeData,Jconsole无需引用自定义对象QueueSample ,因为这个类不存在JConsole的classpath,,通过这种方式,我们无需进行不相关的类引用。

 

消息通知

JMXAPI定义了一种能够使得Mbean发出通知的机制,如当一个状态发生改变的时候,触发事件,发出通知。

为了发出通知,MBean必须实现接口NotificationEmitter或者继承NotificationBroadcasterSupport.当需要发出通知的时候,你必须实例化一个javax.management.Notification或者其子类(如AttributeChangedNotification),通过NotificationBroadcasterSupport.sendNotification.方法将其发出。所有的Notification都需要一个来源,这个来源就是发出该通知的MBean的名字。所有的通知都必须有一个序列号,以便对来自同一个来源的消息进行排序处理,这个序列号可以是0,但建议是自增的。

加入了消息通知的HelloMBean

package com.example;
 
import javax.management.*;
 
public class Hello
        extends NotificationBroadcasterSupport
        implements HelloMBean {
 
    public void sayHello() {
        System.out.println("hello, world");
    }
 
    public int add(int x, int y) {
        return x + y;
    }
 
    public String getName() {
        return this.name;
    }
 
    public int getCacheSize() {
        return this.cacheSize;
    }
 
    public synchronized void setCacheSize(int size) {
        int oldSize = this.cacheSize;
        this.cacheSize = size;
 
        System.out.println("Cache size now " + this.cacheSize);
 
        Notification n = new AttributeChangeNotification(this,
                                sequenceNumber++, System.currentTimeMillis(),
                                "CacheSize changed", "CacheSize", "int",
                                oldSize, this.cacheSize);
 
        sendNotification(n);
    }
 
    @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};
    }
    
    private final String name = "Reginald";
    private int cacheSize = DEFAULT_CACHE_SIZE;
    private static final int DEFAULT_CACHE_SIZE = 200;
    private long sequenceNumber = 1;
}

AttributeChangeNotification 的构造参数包括:

l 消息来源。Hello MBean的名称。

l 序列号,这里是自增的。

l 时间戳。

l 消息通知的内容。

l 变化得属性的名称

l 变化得属性的类型

l 变化得属性的旧值

l 变化后的新值。

 

Jconsole能够在tag中看到通知的相关内容。

 

远程管理

启动JMXAgent

java -Dcom.sun.management.jmxremote.port = 9999  \
     -Dcom.sun.management.jmxremote.authenticate = false \
     -Dcom.sun.management.jmxremote.ssl = false \
     com.example.Main
点开jconsole,选择远程进程,输入hostname:9999,点击连接。
 
 

自定义JMX 客户端

前面我们使用的客户端一直都是系统提供的Jconsole,如果需要我们自定义JMX 客户端呢?比如我们来自己实现进程的监控,管理,统计,告警的ITIL系统,应该如何呢?

引入JMX 远程API类

package com.example;
...
 
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
 
public class Client {

构建通知监听器

ublic static class ClientListener implements NotificationListener {
 
    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());
        if (notification instanceof AttributeChangeNotification) {
            AttributeChangeNotification acn =
                (AttributeChangeNotification) notification;
            echo("\tAttributeName: " + acn.getAttributeName());
            echo("\tAttributeType: " + acn.getAttributeType());
            echo("\tNewValue: " + acn.getNewValue());
            echo("\tOldValue: " + acn.getOldValue());
        }
    }

构建RMI 连接器客户端

Client类构建了一个RMI的链接,他被配置成了在本地访问Main的RMI 连接器Server。

public static void main(String[] args) throws Exception {
 
echo("\nCreate an RMI connector client and " +
    "connect it to the RMI connector server");
JMXServiceURL url = 
    new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);

 

JMXServiceURL中的Url代表了如何找到连接器server,这个URL允许连接器客户端访问注册到本地host和端口9999的RMI服务,connect方法的第二个参数表述环境变量map。

 

远程连接MBean Server

当RMI 链接就绪之后,JMXclient必须连接远程的MBean Server,以使得他能够与注册在JMXAgent中的MBean是进行交互。

MBeanServerConnection mbsc = 
jmxc.getMBeanServerConnection();
我们能够通过如下方法在Mbean Server中查询和获取MBean
echo("\nDomains:");
String domains[] = mbsc.getDomains();
Arrays.sort(domains);
for (String domain : domains) {
    echo("\tDomain = " + domain);
}
        
...
        
echo("\nMBeanServer default domain = " + mbsc.getDefaultDomain());
 
echo("\nMBean count = " +  mbsc.getMBeanCount());
echo("\nQuery MBeanServer MBeans:");
Set<ObjectName> names = 
    new TreeSet<ObjectName>(mbsc.queryNames(null, null));
for (ObjectName name : names) {
    echo("\tObjectName = " + name);
}


通过代理执行远程MBean的操作

mbsc.addNotificationListener(mbeanName, listener, null, null);  //加入监听器
ObjectName mxbeanName = new ObjectName ("com.example:type=QueueSampler");
QueueSamplerMXBean mxbeanProxy = JMX.newMXBeanProxy(mbsc, 
    mxbeanName,  QueueSamplerMXBean.class);
QueueSample queue1 = mxbeanProxy.getQueueSample();
echo("\nQueueSample.Date = " + queue1.getDate());
echo("QueueSample.Head = " + queue1.getHead());
echo("QueueSample.Size = " + queue1.getSize());
echo("\nInvoke clearQueue() in QueueSampler MXBean...");
mxbeanProxy.clearQueue();
 
QueueSample queue2 = mxbeanProxy.getQueueSample();
echo("\nQueueSample.Date = " +  queue2.getDate());
echo("QueueSample.Head = " + queue2.getHead());
echo("QueueSample.Size = " + queue2.getSize());

 

通过newMBeanProxy来构造一个MBean本地代理,如果你选择的是一个MXBean,只需要相应的选择JMX.newMXBeanProxy 即可,通过这种远程调用的方式,你就好像执行本地方法一样的便捷。

 

关闭连接

jmxc.close();
 

最后

JMX的介绍就到此为此了,在这里

            jdk_home/sample/jmx/jmx-scandir

你可以找到更多的JMX以及MBean的实例。

 

参考文献:http://docs.oracle.com/javase/tutorial/jmx/TOC.html

这篇关于Java Management Extensions (JMX)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/940213

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定