即时处理已构建MBean的代码库(用于导出到jmx)。
原始代码只是构建一个MBeanInfo实例:
@Override
public MBeanInfo getMBeanInfo() {
MBeanAttributeInfo[] attrs = //SLOW TO BUILD
return new MBeanInfo(...attrs...);
}
由于mbean属性构建起来很昂贵,并且这种方法被频繁调用(即使没有连接jmx客户端),我还是尝试创建一个懒惰地计算这些属性的MBeanInto的子类:
public class LazyMBeanInfo extends MBeanInfo implements Externalizable {
private transient AttributeCallback callback = null;
private volatile MBeanAttributeInfo[] lazyAttrs = null;
public LazyMBeanInfo(...AttributeCallback callback...) throws IllegalArgumentException {
super(className, description, null, constructors, operations, notifications);
this.callback = callback;
}
@Override
public MBeanAttributeInfo[] getAttributes() {
MBeanAttributeInfo[] val = lazyAttrs;
if (val != null) {
return val.clone(); //match upstream behaviour
}
if (callback == null) {
throw new IllegalStateException("BUG");
}
val = callback.buildAttributes();
if (val == null) {
val = new MBeanAttributeInfo[0];
}
lazyAttrs = val;
return val.clone();
}
public interface AttributeCallback {
MBeanAttributeInfo[] buildAttributes();
}
}
问题是JMX(通过RMI)序列化MBeanInfo对象,然后在jconsole(或jvisualVM)中出现错误:
所以 - 我可以以某种方式实现Externalizable并将自己序列化为父类的实例吗?理想情况下,我喜欢这样的工作:
public class LazyMBeanInfo extends MBeanInfo implements Externalizable {
//same as before, plus:
@Override
public void writeExternal(ObjectOutput out) throws IOException {
MBeanInfo vanilla = new MBeanInfo(...);
out.writeObject(vanilla);
}
}
但它没有。
这有可能吗?
答案 0 :(得分:1)
除非你使用[高度动态]的DynamicMBeans,否则我不明白为什么每次调用getMBeanInfo()
都需要重建MBeanInfo,但是......
您的LazyMBeanInfo可以正常工作(虽然我没有测试过这个特定情况)。 MBeanInfo已经实现了Serializable,所以你想要的是序列化过程写出MBeanInfo而不是LazyMBeanInfo,因为客户端可能在类路径中没有该类。但是,LazyMBeanInfo可以实现此方法:
Object writeReplace() throws ObjectStreamException;
此时你写出了底层的MBeanInfo。请参阅Serializable JavaDoc,具体来说:
需要指定替代对象的可序列化类 在将对象写入流时应该使用它 具有确切签名的特殊方法:
ANY-ACCESS-MODIFIER对象writeReplace()抛出 ObjectStreamException;
这样,实际的对象可以是LazyMBeanInfo的一个实例,但你写的可以是一个实际的MBeanInfo,它是从你的缓存的lazyAttrs构建的。
话虽如此,我不是实现构建一次调用的方法,而是在首次创建MBean时,或者在注册MBean时,通过简单地构建完整的MBeanInfo来实现构建 - 优先使用。 。然后在每个getMBeanInfo()
调用上返回预先构建的MBeanInfo。
要在MBean注册时执行此操作,请实现MBeanRegistration接口,并在postRegister方法中构建缓存的MBeanInfo。