资源描述
shipl@
JMX & MX4J
Made by Michael.Shi
mailto:shipl@
目录
JMX - 3 -
Brief Intro - 3 -
1.概念 - 3 -
2.用途 - 3 -
3.架构 - 3 -
MBean - 5 -
MBeanServer - 5 -
ObjectName - 5 -
Standard MBean - 5 -
Brief Intro - 5 -
例子&解析: - 6 -
Dynamic MBean - 8 -
Brief Intro - 8 -
MBeanInfo: - 9 -
例子&解析: - 11 -
RMI连接 - 17 -
例子&解析: - 18 -
MX4J - 25 -
Brief Intro - 25 -
例子&解析: - 26 -
JMX
Brief Intro
1.概念
JMX(Java Management Extensions)是一个为应用程序植入管理功能的框架。JMX是一套标准的代理和服务,实际上,用户可以在任何Java应用程序中使用这些代理和服务实现管理。
2.用途
JMX可以跨越一系列异构操作系统平台、系统体系结构和网络传输协议,灵活的开发无缝集成的系统、网络和服务管理应用。
3.架构
设备层(Instrumentation Level):各种MBean
MBean有各种元数据(meta data):
• Attributes, which contain the state of the resource
• Constructors, which are used by management applications and other JMX agents to create instances of the resource
• Operations, which may be invoked by a management application or other JMX agent to cause the resource to perform some action
• Parameters to constructors and operations
• Notifications, which are emitted by the resource and sent via the JMX notification infrastructure to any interested agents
What is MBean?
1. 需要有getter & setter 方法;
2. 通过JMX Mbean的一种类型来操作(instrument),即standard, dynamic, model, or open;
3. 至少有一个构造函数;
4. 不能是Abstract类型的。
代理层(Agent Level):核心是一个MBeanServer,所有MBean都要在此注册,才能被管理。注册在这里的MBean并不直接和远程应用程序进行通信,是通过协议adaptor和connector进行通信。而adaptor和connector也以MBean的形成要进行注册。
在注册MBean时,必须为每一个MBean提供唯一的ObjectName。管理应用程序用这个对象名进行标识管理构件并对其操作。
分布服务层(Distributed Service Level):
当前的JMX规范并没有给出这一层的具体规范。
该层规定了实现JMX应用管理平台的接口。这一层定义了能对代理层进行操作的管理接口和组件。这些组件能:
1)为管理应用程序提供一个接口,以便它通过一个连接器能透明和代理层或者JMX管理资源进行交互。
2)通过各种协议的映射(如SNMP、HTML等),提供了一个JMX代理和所有可管理组件的视图。
3)分布管理信息,以便构造一个分布式系统,也就是将高层管理平台的管理信息向其下众多的JMX代理发布。
4)收集多个JMX 代理端的管理信息并根据管理终端用户的需要筛选用户感兴趣的信息并形成逻辑视图送给相应的终端用户。
5)提供了安全保证。
MBean
MBeanServer
该接口用来管理注册在MBeanServer中的MBean。
获得方法:
MBeanServerFactory.createMBeanServer();
MBeanServerFactory.newMBeanServer();
ManagementFactory.getPlatformMBeanServer();
区别:
createMBeanServer所创建出的MBeanServer的引用内部保存(MBeanServer reference is internally kept),所以可以由findMBeanServer来获得该MBeanServer的引用。
newMBeanServer 没有内部保存引用,若MBeanServer不再用了,GC会回收掉。
ObjectName
构造方法:
ObjectName(String name):name格式为“DomainName:key=value”.
ObjectName(String domain,String key,String value)
ObjectName(String domain,Hashtable<String,String> table)
注意:ObjectName初始化时会抛出异常,需要进行捕获,或者在方法上抛出。
Standard MBean
Brief Intro
1. 需要有一个接口;
2. 需要有一个实现该接口的类。
注意:接口必须命名为实现类+MBean,如果接口名字不对,会报错,说没有按照standard MBean convention约定。
例子&解析:
接口:
package com.primeton.spl;
public interface HelloMBean
{
public String getName();
public void setName(String name);
public void printHello();
public void printHello(String whoName);
}
实现类:
package com.primeton.spl;
public class Hello implements HelloMBean
{
private String name;
public Hello()
{
this.name = "This is default name from default constructor .";
}
public Hello(String name)
{
this.name = name + ": from constructor with a param";
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public void printHello()
{
System.out.println("Hello World, " + name);
}
public void printHello(String whoName)
{
System.out.println("Hello , " + whoName);
}
}
JMX Agent 类:
package com.primeton.spl;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;
import m.HtmlAdaptorServer;
public class HelloAgent
{
public static void main(String[] args) throws Exception
{
MBeanServer server = MBeanServerFactory.createMBeanServer();
// MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName helloName = new ObjectName("Michael_Shi:name=HelloWorld");
server.registerMBean(new Hello(), helloName);
ObjectName adapterName = new ObjectName("HelloAgent:name=htmladapter");
HtmlAdaptorServer adapter = new HtmlAdaptorServer();
adapter.setPort(9999);
server.registerMBean(adapter, adapterName);
adapter.start();
System.out.println("start.....");
}
}
解析:
HelloMBean是接口,且命名必须为XXX 实现类类名
+ MBean,里面定义了各种业务方法。
Hello类是接口的实现类,里面实现了业务方法。
注意:MBean的属性的读写性是在接口HelloMBean中定义的,由getter方法进行读,setter方法进行写,可以根据具体属性的读写性进行删减。
MBServer 对MBean通过register方法进行注册。
HtmlAdaptorServer
需要加入jmxtools.jar。
这里提供了用浏览器进行查看注册在MBServer中的MBean的方法。相当于浏览器是client end。它也是一个MBean,也需要在MBServer中进行注册。并且还需要调用start方法。
注意:当使用htmpAdaptor时,如果需要设置port,
1.可以在ObjectName中设置ObjectName adapterName = new ObjectName("HelloAgent:name=htmladapter,port=9999");
2.可以通过adaptor.setPort(9999);设置。推荐后者。
注意:可以对htmladapter添加验证身份
// 添加验证功能
AuthInfo在jmxtools.jar中
login = new AuthInfo();
login.setLogin("admin");
login.setPassword("admin");
adapter.addUserAuthenticationInfo(login);
MBeanServer在注册MBean后,可以通过setAttribute对其属性进行修改。
可以应用于不能修改源代码的第三方jar包。
setAttribute(ObjectName name,Attribute attribute)
运行后,打开浏览器,在地址栏输入localhost: 9999 即可以看到注册的MBean.
Dynamic MBean
Brief Intro
继承javax.management.DynamicMBean 的Mbean就是Dynamic Mbean
注意:一个MBean不能同时是Dynamic和Standard的,即不能同时继承两个接口(一个自己MBean的接口,一个DynamicMBean接口)。
继承该接口,就要实现下面各方法:
public Object getAttribute( String attribute )
public void setAttribute( Attribute attribute )
public AttributeList getAttributes( String[] attributes );
public AttributeList setAttributes( AttributeList attributes );
public Object invoke( String actionName, Object[] params, String[] signature )
public MBeanInfo getMBeanInfo();
通过getAttribute和getAttributes来获得属性,setAttribute和setAttributes来设置属性。
Invoke方法参数:
String:要调用的方法名;
Object[]:调用方法的参数值;
String[]:方法的参数值类型。
When Dynamic MBean?
1. 当你不能改变代码却想要对其资源进行管理时(例如第三方jar包);
2. 资源的受管接口经常变化时。
Why Dynamic MBean?
1. 更加简单地对现存代码进行instrument;
2. 可以对受管资源提供description(is not avaiable for standard MBean)
3. 你还可以在运行期间新创建一些受管资源(例如:新建方法、属性等)。
MBeanInfo:
包含MBean元数据的容器。
MBeanInfo类的实例能够通过调用getClassName()和getDescription()来获得MBean的类名和描述。
在Dynamic MBean中,最终要由将所有的其他Info创建成MBeanInfo。
MBeanFeatureInfo:
是所有MBean元数据的超类,含有name和description,所以其他的元数据类都有name和description。
MBeanParameterInfo:
描述了构造函数和方法中的参数名、描述,还增加了参数的类型。这三个就足够定义方法的参数了。
MBeanConstructorInfo:
描述了MBean类的构造函数。可以通过constructor或者name、description、MBeanParameterInfo[]来进行构造(具体见API)。
该类只有一个方法:getSignature(),返回MBeanParameterInfo[] 。
MBeanAttributeInfo:
描述暴露出的属性信息。
可以通过传入相关属性信息来构造,也可以通过传入Method for getter & setter来进行构造(见API)。
通过调用下列方法来获得信息:
getType()——获得属性类型;
isReadable()——是否可读,如果为true,需要提供getter方法;
isWritable()——是否可写,如果为true,需要提供setter方法;
isIs()——是否可以用is获得(boolean类型)。
注意:在构造方法中,第一个参数为name(The name of the attribute),如果你的属性是小写,例如password,那么在这个构造方法中,你需要把其首字母大写,即为Password。因为参数的读写时通过getter和setter 方法进行访问,但是实际上生成getter、setter方法时是getPassword,和setPassword。所以,如果你在构造函数的参数中依旧写上小写的password,则会找不到setter、getter,使得没有办法取值、读值。
MbeanOperationInfo:
描述暴露出的方法信息。
可以通过传入Method来构造,也可以通过传入相应方法信息来构造(见API)。
其中,构造参数中int类型的impact取值如下:
■ INFO—The operation returns information, similar to a getter method.
■ ACTION—The operation causes a change or action on the MBean.
■ ACTION_INFO—The operation results in a combination of the INFO and ACTION impact.
■ UNKNOWN—The impact of the operation is unknown.
MBeanNotificationInfo:
描述了MBean发出的notification信息。
例子&解析:
HelloDynamic类:
import java.lang.reflect.Constructor;
import java.util.Iterator;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.DynamicMBean;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanConstructorInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.ReflectionException;
/**
** @author Sunny Peng
* @author change by Chen.Gang, add a feature for dynamic add operation
* @author edit from Michael.Shi
* * @version 1.0 19.
*/
public class HelloDynamic implements DynamicMBean
{
// 这是我们的属性名称
private String name;
private MBeanInfo mBeanInfo = null;
private String className;
private String description;
private MBeanAttributeInfo[] attributes;
private MBeanConstructorInfo[] constructors;
private MBeanOperationInfo[] operations;
MBeanNotificationInfo[] mBeanNotificationInfoArray;
public HelloDynamic()
{
init();
buildDynamicMBean();
}
private void init()
{
className = this.getClass().getName();
description = "Simple implementation of a dynamic MBean.";
attributes = new MBeanAttributeInfo[1];
constructors = new MBeanConstructorInfo[1];
operations = new MBeanOperationInfo[1];
mBeanNotificationInfoArray = new MBeanNotificationInfo[0];
}
private void buildDynamicMBean()
{
// 设定构造函数
Constructor[] thisconstructors = this.getClass().getConstructors();
constructors[0] = new MBeanConstructorInfo(
"HelloDynamic(): Constructs a HelloDynamic object",
thisconstructors[0]);
// 设定一个属性
attributes[0] = new MBeanAttributeInfo("Name", "java.lang.String",
"Name: name string.", true, true, false);
// operate method 我们的操作方法是print
MBeanParameterInfo[] params = null;// 无参数
operations[0] = new MBeanOperationInfo("print",
"print(): print the name", params, "void",
MBeanOperationInfo.INFO);
mBeanInfo = new MBeanInfo(className, description, attributes,
constructors, operations, mBeanNotificationInfoArray);
System.out.println("First : " + mBeanInfo.getClassName() + ": " + mBeanInfo.getDescription());
}
// 动态增加一个print1方法
private void dynamicAddOperation()
{
init();
operations = new MBeanOperationInfo[2];// 设定数组为两个
buildDynamicMBean();
operations[1] = new MBeanOperationInfo("print1",
"print1(): print the name", null, "void",
MBeanOperationInfo.INFO);
mBeanInfo = new MBeanInfo(className, description, attributes,
constructors, operations, mBeanNotificationInfoArray);
System.out.println(mBeanInfo.getClassName() + ": " + mBeanInfo.getDescription());
}
public Object getAttribute(String attribute_name)
{
if (attribute_name != null)
return null;
if (attribute_name.equals("Name"))
return name;
return null;
}
public void setAttribute(Attribute attribute)
{
if (attribute == null)
return;
String Name = attribute.getName();
Object value = attribute.getValue();
try
{
if (Name.equals("Name"))
{
// if null value, try and see if the setter returns any
// exception
if (value == null)
{
name = null;
// if non null value, make sure it is assignable to the
// attribute
} else if ((Class.forName("java.lang.String"))
.isAssignableFrom(value.getClass()))
{
name = (String) value;
}
}
} catch (Exception e)
{
e.printStackTrace();
}
}
public AttributeList getAttributes(String[] attributeNames)
{
if (attributeNames == null)
return null;
AttributeList resultList = new AttributeList();
// if attributeNames is empty, return an empty result list
if (attributeNames.length == 0)
return resultList;
for (int i = 0; i < attributeNames.length; i++)
{
try
{
Object value = getAttribute(attributeNames[i]);
resultList.add(new Attribute(attributeNames[i], value));
} catch (Exception e)
{
e.printStackTrace();
}
}
return resultList;
}
public AttributeList setAttributes(AttributeList attributes)
{
if (attributes == null)
return null;
AttributeList resultList = new AttributeList();
// if attributeNames is empty, nothing more to do
if (attributes.isEmpty())
return resultList;
// for each attribute, try to set it and add to the result list if
// successfull
for (Iterator i = attributes.iterator(); i.hasNext();)
{
Attribute attr = (Attribute) i.next();
try
{
setAttribute(attr);
String name = attr.getName();
Object value = getAttribute(name);
resultList.add(new Attribute(name, value));
} catch (Exception e)
{
e.printStackTrace();
}
}
return resultList;
}
public Object invoke(String operationName, Object params[],
String signature[]) throws MBeanException, ReflectionException
{
// Check for a recognized operation name and call the corresponding
// operation
if (operationName.equals("print"))
{
// 具体实现我们的操作方法print
System.out.println("Hello, " + name + ", this is HellDynamic!");
dynamicAddOperation();
return null;
} else if (operationName.equals("print1"))
{
System.out.println("这是动态增加的一方法print1");
return null;
} else
{
// unrecognized operation name:
throw new ReflectionException(new NoSuchMethodException(
operationName), "Cannot find the operation "
+ operationName + " in " + className);
}
}
public MBeanInfo getMBeanInfo()
{
return mBeanInfo;
}
}
HelloAgent(Html管理)类:
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;
import m.HtmlAdaptorServer;
public class HelloAgent
{
public static void main(String[] args) throws Exception
{
MBeanServer server = MBeanServerFactory.createMBeanServer();
ObjectName helloName = new ObjectName("Michael_Shi:name=HelloDynamic");
HelloDynamic hello = new HelloDynamic();
server.registerMBean(hello, helloName);
ObjectName adapterName = new ObjectName(
"HelloAgent:name=htmladapter,port=8082");
HtmlAdaptorServer adapter = new HtmlAdaptorServer();
server.registerMBean(adapter, adapterName);
// 添加验证功能
AuthInfo login = new AuthInfo();
login.setLogin("admin");
login.setPassword("admin");
adapter.addUserAuthenticationInfo(login);
adapter.start();
System.out.println("start.....");
}
}
需要添加jmxtools.jar。
JconsoleAgent(Jconsole管理)类:
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;
/**
* @author Michael.Shi
*
*/
public class JConsoleAgent {
public static void main(String[] args) throws Exception {
MBeanServer server=MBeanServerFactory.createMBeanServer();
LocateRegistry.createRegistry(9999);
HelloDynamic hello = new HelloDynamic();
ObjectName helloName = new ObjectName("Michael_Shi:name=HelloDynamic");
server.registerMBean(hello, helloName);
JMXServiceURL url=new JMXServiceURL("service:jmx:rmi:///jndi/rmi://127.0.0.1:9999/server");
JMXConnectorServer cs=JMXConnectorServerFactory.newJ
展开阅读全文