我正在处理已构建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);
}
}
但事实并非如此。
这可能以某种方式吗?
最佳答案
除非您使用[高度动态] DynamicMBeans,否则我不明白为什么每次调用getMBeanInfo()
都需要重建MBeanInfo,但是...。
可以使您的LazyMBeanInfo正常工作(尽管我尚未测试此特定情况)。 MBeanInfo已经实现了Serializable,所以您需要在序列化过程中写出MBeanInfo而不是LazyMBeanInfo,因为客户端的类路径中可能没有该类。但是,LazyMBeanInfo可以实现此方法:
Object writeReplace() throws ObjectStreamException;
此时,您将写出基础MBeanInfo。请参阅Serializable JavaDoc,特别是:
需要指定替代对象的可序列化类
在将对象写入流时应使用此实现
具有确切签名的特殊方法:
ANY-ACCESS-MODIFIER对象writeReplace()引发
ObjectStreamException;
这样,实际对象可以是LazyMBeanInfo的实例,但是您写出的内容可以是根据缓存的lazyAttrs构建的实际MBeanInfo。
话虽如此,而不是实现首次调用构建方法,而是通过在首次创建MBean或注册MBean时简单地构建完整的MBeanInfo来实现先使用后构建。然后,只需在每个
getMBeanInfo()
调用上返回预构建的MBeanInfo。要在MBean注册时执行此操作,请实现MBeanRegistration接口,并在postRegister方法中构建缓存的MBeanInfo。
关于java - 使子类序列化为父类(super class)的实例?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50768567/