make subclass serialize作为超类的一个实例?

时间:2018-06-08 21:24:32

标签: java serialization jmx

即时处理已构建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)中出现错误: enter image description here

所以 - 我可以以某种方式实现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);
    }
}

但它没有。

这有可能吗?

1 个答案:

答案 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。