首页 > 其他分享 >jmx 首试

jmx 首试

时间:2023-05-17 19:32:43浏览次数:26  
标签:jmx 0.0 void public 首试 MBean import throws


 

 

举一个应用实例:在一个系统中常常会有一些配置信息,比如服务的IP地址,端口号什么的,那么如何来写这些代码呢?

  1. 程序初哥一般是写死在程序里,到要改变时就去改程序,然后再编译发布;
  2. 程序熟手则一般把这些信息写在一个配置文件里(JAVA一般都是*.properties文件),到要改变时只要改配置文件,但还是重新启动系统,以便读取配置文件里的新值;
  3. 程序好手则会写一个段代码,把配置值缓存起来,系统在读值的时候,先看看配置文件有没有更动。如有更改则重读一遍,否则从缓存里读取值
  4. 程序高手则懂得取物为我所用,用JMX!把配置属性集中在一个类,然后写一个叫MBean的东东,再配置一下就轻松搞定了。而且JMX自动提供了一个WEB页面来给你来改变这些配置信息。

 

 

 

 

 

 

  • RMI(Remote Method Invocation)

RMI是不同JVM之间的对象通信的协议

  • JMX RMI访问的基本步骤:

1

启动MBeanServer

2

建立并启动 NamingService MBean,实际就是rmiregistry

3

为MBeanServer建立160 JMX RMIConnector,此RMI连接器提供:

service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxconnector

4

客户端连接


4.1

通用客户端(如jconsole)

4.2

自定义客户端

生成 JMXConnector ,与JMI server建立 RMI连接

建立与MBean server的连接

MBeanServerInvocationHandler.newProxyInstance()获取代理MBean


  • JMX RMI例子

1. RMI Server

package com.machome.jmx.appTest;

 import javax.management.MBeanServer;
 import javax.management.MBeanServerFactory;
 import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
 import javax.management.remote.JMXConnectorServer;
 import javax.management.remote.JMXConnectorServerFactory;
 import javax.management.remote.JMXServiceURL;

 import com.machome.bean.Hello;

 import mx4j.tools.naming.NamingService;


 public class RmiServer
 {
     private MBeanServer mBeanServer;
     private JMXConnectorServer connectorServer;
     private JMXServiceURL jmxUrl;
    
     public RmiServer() throws Exception{
           mBeanServer = MBeanServerFactory.createMBeanServer();
           createRmiregistry();
           CreateJMXConnector();
     }
    public static void main(String[] args) throws Exception
    {
      
        RmiServer rmiServer = new RmiServer();
        // 加一个测试MBean Hello对象
        rmiServer.addMbean(new Hello(), "mbean", "name", "hello");
        rmiServer.startJMXConnector();
       
        System.out.println("Server up and running");
    }
   
    public ObjectName addMbean(Object o,String domain,String key,String value) throws Exception{
           ObjectName oName = new ObjectName(domain, key, value);
           mBeanServer.registerMBean(o, oName);
           return oName;
 }
   
   
    public void createRmiregistry() throws Exception{
          
           // 1.注册NamingService MBean
           ObjectName namingName = ObjectName
                       .getInstance("naming:type=rmiregistry");
        
        
          
           mBeanServer.registerMBean(ns, namingName);
           // 2.启动NamingService MBean
           mBeanServer.invoke(namingName, "start", null, null);
    }
   
   
    public void CreateJMXConnector() throws Exception{

           // 1.nammingPort,从NamingService获得Port,缺省是1099
           ObjectName namingName = ObjectName.getInstance("naming:type=rmiregistry");
      int namingPort = ((Integer)mBeanServer.getAttribute(namingName, "Port")).intValue();
         
           // 2. jndiPath
           String jndiPath = "/jmxconnector";
           // 3. JMXServiceURL ,为:
           // service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxconnector
           jmxUrl = new JMXServiceURL("service:jmx:rmi://localhost/jndi/rmi://localhost:"
                                               + namingPort + jndiPath);
          
           // 4.Create and start the RMIConnectorServer
           // 中间设为null的参数,是针对认证的,我们这里没打开,设为null
              connectorServer = JMXConnectorServerFactory
                                   .newJMXConnectorServer(jmxUrl, null, mBeanServer);
    }
   
    public void startJMXConnector() throws Exception{
        connectorServer.start();
    }
   
    public void stopJMXConnector() throws Exception{
        connectorServer.stop();
    }
   
 }


执行此RmiServer:

Server up and running



可以看到TCP 1099端口被listen

D:Documents and Settingsmac>netstat -an


Active Connections


  Proto  Local Address          Foreign Address        State

  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING

  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING

  TCP    0.0.0.0:1025           0.0.0.0:0              LISTENING

TCP    0.0.0.0:1099           0.0.0.0:0             

  TCP    0.0.0.0:2737           0.0.0.0:0              LISTENING

  TCP    0.0.0.0:3306           0.0.0.0:0              LISTENING

  TCP    0.0.0.0:6059           0.0.0.0:0              LISTENING

  TCP    0.0.0.0:6648           0.0.0.0:0              LISTENING

2.通用客户端(典型的比如jconsole)


这里用的是jdk 1.6 jconsole

远程进程:

service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxconnector


用户名:

口令:

用户名和口令都可以空着,不必输入

点"连接",可以进入jconsole界面

可以在mbean下看到hello对象

3. 自定义client 端通过RMI连接 Server


执行:
 Server up and running
 Hello, mac
 Hello, haha
package com.machome.jmx.appTest;

 import javax.management.JMX;
 import javax.management.MBeanServerConnection;
 import javax.management.MBeanServerDelegateMBean;
 import javax.management.MBeanServerInvocationHandler;
 import javax.management.ObjectName;
 import javax.management.remote.JMXConnector;
 import javax.management.remote.JMXConnectorFactory;
 import javax.management.remote.JMXServiceURL;

 import com.machome.bean.Hello;
 import com.machome.bean.HelloMBean;



 public class RmiClient
 {
     private JMXServiceURL jmxUrl;
     private JMXConnector connector;
     private MBeanServerConnection mBeanServerconnection;
    
    
     public RmiClient()throws Exception{
         createJMXRmiConnector();
         createMBeanServerConnection();
     }
    
    public static void main(String[] args) throws Exception
    {
        new RmiClient().test();
       
    }
   
   
    private void createJMXRmiConnector() throws Exception{
           // 1.The JMXConnectorServer protocol
           String serverProtocol = "rmi";

           // 2.The RMI server's host
           // this is actually ignored by JSR 160
           String serverHost = "localhost";

           // 3.The host, port and path where the rmiregistry runs.
           String namingHost = "localhost";
           int namingPort = 1099;
           String jndiPath = "/jmxconnector";

           // 4. connector server url
           jmxUrl = new JMXServiceURL("service:jmx:" +
                   serverProtocol + "://" + serverHost +
                   "/jndi/rmi://" + namingHost + ":" +
                   namingPort + jndiPath);
          
           // 5. 生成 JMXConnector,连接到url一端
           // Connect a JSR 160 JMXConnector to the server side
           connector = JMXConnectorFactory.connect(jmxUrl);

    }
   
   
    private void createMBeanServerConnection() throws Exception{
        mBeanServerconnection = ();
    }   
    public void test()throws Exception{
  
        ObjectName  oName = new ObjectName("mbean", "name", "hello");
        // 获取代理对象
        Object proxy = MBeanServerInvocationHandler
         .newProxyInstance(mBeanServerconnection,oName, HelloMBean.class, true);
                 

        
         // 获取测试MBean,并执行它的(暴露出来被管理监控的)方法      
        HelloMBean helloMBean = (HelloMBean)proxy;
       
        helloMBean.setName("mac");
        helloMBean.printHello();
        helloMBean.printHello("haha");
    
    }
   
 }
   
    public void test()throws Exception{
  
        ObjectName  oName = new ObjectName("mbean", "name", "hello");
        // 获取代理对象
        Object proxy = MBeanServerInvocationHandler
         .newProxyInstance(mBeanServerconnection,oName, HelloMBean.class, true);
                 

        
         // 获取测试MBean,并执行它的(暴露出来被管理监控的)方法      
        HelloMBean helloMBean = (HelloMBean)proxy;
       
        helloMBean.setName("mac");
        helloMBean.printHello();
        helloMBean.printHello("haha");
    
    }
   
 }
执行:
 Server up and running
 Hello, mac
 Hello, haha
   
    public void test()throws Exception{
  
        ObjectName  oName = new ObjectName("mbean", "name", "hello");
        // 获取代理对象
        Object proxy = MBeanServerInvocationHandler
         .newProxyInstance(mBeanServerconnection,oName, HelloMBean.class, true);
                 

        
         // 获取测试MBean,并执行它的(暴露出来被管理监控的)方法      
        HelloMBean helloMBean = (HelloMBean)proxy;
       
        helloMBean.setName("mac");
        helloMBean.printHello();
        helloMBean.printHello("haha");
    
    }
   
 }


  • 上面例子中RMI中的rmiregistry MBean,我们采用的mc4j-tools.jar中的 NamingService,代码如下,代码并不复杂,其实我们也可以自定义一个代替它:

public class NamingService  implements NamingServiceMBean
 {
     public NamingService()
     {
         this(1099);
     }

     public NamingService(int port)
     {
         setPort(port);
     }

     public void setPort(int port)
     {
         if(isRunning())
         {
             throw new IllegalStateException("NamingService is running, cannot change the port");
         } else
         {
             m_port = port;
             return;
         }
     }

     public int getPort()
     {
         return m_port;
     }

     public boolean isRunning()
     {
         return m_running;
     }

     public void start()
         throws RemoteException
     {
         if(!isRunning())
         {
             m_registry = LocateRegistry.createRegistry(getPort());
             m_running = true;
         }
     }

     public void stop()
         throws NoSuchObjectException
     {
         if(isRunning())
             m_running = !UnicastRemoteObject.unexportObject(m_registry, true);
     }

     public String[] list()
         throws RemoteException
     {
         if(!isRunning())
             throw new IllegalStateException("NamingService is not running");
         else
             return m_registry.list();
     }

     public void unbind(String name)
         throws RemoteException, NotBoundException
     {
         if(!isRunning())
         {
             throw new IllegalStateException("NamingService is not running");
         } else
         {
             m_registry.unbind(name);
             return;
         }
     }

     private int m_port;
     private Registry m_registry;
     private boolean m_running;
 }

MBean接口:

public interface NamingServiceMBean
 {

     public abstract void setPort(int i);

     public abstract int getPort();

     public abstract boolean isRunning();

     public abstract void start()
         throws RemoteException;

     public abstract void stop()
         throws NoSuchObjectException;

     public abstract String[] list()
         throws RemoteException;

     public abstract void unbind(String s)
         throws RemoteException, NotBoundException;
 }



  • spring 下的 RMI connector

1.spring 配置如下:

 

<!-- 1.定义自己的bean -->
     <bean id="hello" class="com.machome.bean.Hello" />  
    
     <!-- JMX configuration -->

     <!-- 2.创建一个mbeanServer bean-->
     <!--  如果你的spring是应用在容器中,则不需要此步骤,此步骤用于单独建立独立的MBeanServer中
     <bean id="mbeanServer"
           class="org.springframework.jmx.support.MBeanServerFactoryBean">
     </bean>   
     -->
        
     <!-- 3.定义assembler bean ,装配bean
         MetadataMBeanInfoAssembler是AutodetectCapableMBeanInfoAssembler 唯一实现
         spring文档中有专门介绍AutodetectCapableMBeanInfoAssembler的章节
      -->
     <bean id="assembler"
           class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
         <!-- 注入下面定义的jmxAttributeSource--> 
         <property name="attributeSource" ref="jmxAttributeSource"/>
     </bean>
        
     <!-- 4.定义解释mbean中Annotation的bean-->
     <bean id="jmxAttributeSource"
           class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>


   
   <bean id="registry"     
          class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"
          destroy-method="destroy"> 
     <property name="port" value="1099" /> 
  
            
    <bean id="serverConnector"
        class="org.springframework.jmx.support.ConnectorServerFactoryBean"
        depends-on="registry">

      

      

      

     

       

<!--  如果上面步骤2.你单独定义一个mbeanServer,这里需要指定,否则rmi connector缺省是去寻找runtime环境内的MBeanserver(通常是容器的MBeanServer)
         <property name="server" ref="mbeanServer"/>
         -->
      
      
      
       <!-- 多线程启动connector,thread daemon --> 
       <property name="daemon" value="true" /> 
  
   
    
     <!-- 6.定义MBeanExporter bean, 这是spring jmx最核心的类 -->
     <bean id="mBeanExporter" class="org.springframework.jmx.export.MBeanExporter"
    lazy-init="false">
         <!-- 注入上面定义的assembler 两个bean注入-->
         <property name="assembler" ref="assembler"/>
        
         <!--  如果上面步骤2.你单独定义一个mbeanServer,这里需要指定,否则export bean缺省是去寻找runtime环境内的MBeanserver(通常是容器的MBeanServer)
         <property name="server" ref="mbeanServer"/>
         -->
        
         <!-- 将1.里面定义的mbean注册到mBeanExporter bean中 -->
         <property name="beans">
             <map>
                 <entry key="mbean:name=hello" value-ref="hello"/>
             </map>
         </property>
        
     </bean>

2. web.xml装载spring 配置


  

<!-- ##################### 初始化spring容器  ###########-->   
     <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
                classpath:ssh-mysql.xml
         </param-value>
     </context-param>
     <listener>
         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
     </listener>

3.将项目部署入Tomcat


启动Tomcat

不需要执行任何servlet,action,只要spring随Tomcat启动,就会看到TCP 1099端口被listen

D:Documents and Settingsmac>netstat -an


Active Connections


  Proto  Local Address          Foreign Address        State

  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING

  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING

  TCP    0.0.0.0:1025           0.0.0.0:0              LISTENING

TCP    0.0.0.0:1099       0.0.0.0:0          

  TCP    0.0.0.0:2737           0.0.0.0:0              LISTENING   

4. 执行通用客户端(典型的比如jconsole)


这里用的是jdk 1.6 jconsole

远程进程:

service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxconnector


用户名:

口令:

用户名和口令都可以空着,不必输入

 

点"连接",可以进入jconsole界面

与前面application RMI的例子不同,这里的不仅可以看到hello MBean对象,还能看到很多MBean对象,如Catalina目录下的很多MBean,因为spring没有定义新的MBeanServer,而是用 tomcat容器自己的MBeanServer,所以能看到很多Tomcat容器自己的service MBean

5.执行前面application RMI的例子的RmiClient


Hello, mac

Hello, haha

(我在spring rmi 例子和application rmi 例子 用的相同的serviceUrl ,都是


service:jmx:rmi://localhost/jndi/rmi: //localhost:1099/jmxconnector


因此客户端可以访问这两种例子的Server)




  • 简化后的spring RMI

其实spring 例子里的spring 配置的no.2,no.3.no.4都可以不用
MBeanServer可以不用建立,spring会自动搜索容器自己的MBeanServer,
MBeanInfoAssembler和AnnotationJmxAttributeSource 则只是提供注释MBean功能,以代替implement MBean接口,完全可以不用这种注释,而用传统的implement MBean接口


  

<!-- 1.定义自己的bean -->
     <bean id="hello" class="com.machome.bean.Hello" />
    
     <!-- 5.定义 RMI连接器,注意需要先定义一个naming 注册 bean-->
     <bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean" destroy-method="destroy"> 
       <property name="port" value="1099" /> 
     </bean>
            
     <bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean" depends-on="registry"> 
         <property name="objectName" value="connector:name=rmi"/>
         <property name="serviceUrl" value="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxconnector"/>

        
         <!-- 多线程启动connector,一个线程一个connector -->
         <property name="threaded" value="true" />
         <!-- 多线程启动connector,thread daemon --> 
         <property name="daemon" value="true" /> 
     </bean>
    
    
     <!-- 6.定义MBeanExporter bean, 这是spring jmx最核心的类 -->
     <bean id="mBeanExporter" class="org.springframework.jmx.export.MBeanExporter"
    lazy-init="false">
        
         <!-- 将1.里面定义的mbean注册到mBeanExporter bean中 -->
         <property name="beans">
             <map>
                 <entry key="mbean:name=hello" value-ref="hello"/>
             </map>
         </property>
        
     </bean>

 

 

 

 

标签:jmx,0.0,void,public,首试,MBean,import,throws
From: https://blog.51cto.com/u_15012132/6293341

相关文章

  • JVM系列---【使用jmx_agent监控java程序】
    使用jmx_agent监控java程序1.下载jmx_prometheus_javaagent.jar从https://github.com/prometheus/jmx_exporter/releases下载最新版本的jmx_prometheus_javaagent.jar2.创建一个名为jmx_exporter_config.yml的文件用于配置jmx_prometheus_javaagent.jar的监控参数。该文件应......
  • Java项目开启JMX:Prometheus数据上报
    对于Java项目而言,开启JMX进行JVM监控是很有必要的,可以帮忙开发人员分析、定位问题常规开启JavaJMX方法一般可以在启动脚本中添加相关的参数-Dcom.sun.management.jmxremote.port=6543-Dcom.sun.management.jmxremote.authenticate=false-Dcom.sun.management.jmxremote.ssl=......
  • re/【unity】游戏逆向首试 [BJDCTF2020]BJD hamburger competition
    本题是是一个unity游戏,而且是以c#和.net编写尝试直接用idea进行反汇编,但是没有找到运行逻辑,后来在大佬的wp上发现是利用dnspy对c#的dll文件进行返回编,进而获得结果。反汇编BJDhanburgercompetirion_Data中的Assembly-CSharp.dll即可获得如下代码段:可以看到先利用sha1进行加......
  • Tomcat监控原理cmdline-jmxclient-0.10.3.jar源码解析
    【摘要】cmdline-jmxclient-0.10.3.jar是一个开源jar包,在zabbix3.0中常用于测试的一个工具,可以用来测试jmx是否配置正确。在监控方面后还可以对Tomcat各种属性进行监控。......
  • J2EE之JMX技术分析
    简介JMX(JavaManagementExtensions,即Java管理拓展)。JMX可以让JDK自检测程序。常用于管理线程、内存、日志Level、服务重启、系统环境,让开发者可以获取程序运行的状态和......
  • Zabbix监控Tomcat开启JMX时修改catalina.sh文件后tomcat服务起不来/配置catalian.sh不
    zabbix监控tomcat,开启JMX修改catalina.sh文件,tomcat服务起不来问题现象(配置Catalina.sh脚本,开启JMX不起效)问题一:配置完脚本,重启tomcattomcat服务启动失败查看tomcat的ca......
  • 关于解决activemq jmx连接获取连接数等信息问题记录
    简易https://blog.csdn.net/Caiabcd/article/details/119532434management更改https://www.cnblogs.com/eric-fang/p/11431104.htmlip更改https://www.bbsmax.com/A/1......
  • JMX攻击方式以及理论文章
    这里就简单记录一下其中遇到比较常见的一些东西吧。比如jmx的地址:service:jmx:rmi://localhost:1099/jndi/rmi://localhost:8899/mynameservice:jmx:是JMXURL的标......
  • jmxterm 基于jmx 的开源cli 工具
    实际上就是一个类似jconsole的可选工具,还是很不错的,使用简单,比如适合在linux以及对于容器环境参考使用下载 直接通过官方地址就可以了运行说明apachekafka......
  • 使用jmx exporter采集kafka指标
    预置条件安装kafka、prometheus使用JMXexporter暴露指标下载jmxexporter以及配置文件。Jmxexporter中包含了kafka各个组件的指标,如servermetrics、producermetrics......