1

我目前有一些在声明中初始化的字段的类,如下所示:

public class SomeClass implements Externalizable {

    private long id; 

    private final List<Hit> hits = new ArrayList<>();

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeLong(id);
        out.writeInt(hits.size());
        for (int i = 0; i < hits.size(); i++) {
            out.writeObject(hits.get(i));
        }
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        id = in.readLong();
        int size = in.readInt();
        for (int i = 0; i < size; i++) {
             hits.add((Hit) in.readObject()); //<--Nullpointer here, hits == null
        }
    }
}

并且此类用于基于文件的chronicle-map配置,如下所示:

ChronicleMap<Long, SomeClass> storage = ChronicleMapBuilder
            .of(Long.class, SomeClass.class)
            .averageValueSize(avgEntrySize)
            .entries(entries)
            .createPersistedTo(new File(path));

问题是,当我重新启动我的应用程序时,我会NullpointerException在编年史尝试读取保存的地图时得到,因为hits字段没有初始化,这意味着它是null.

我做了一些调查,发现在调用chronical之前使用(in )readExternal创建了这个类的对象:UNSAFE.allocateInstanceExternalizableMarshaller

protected E getInstance() throws Exception {
    return (E) NativeBytes.UNSAFE.allocateInstance(classMarshaled);
}

所以基本上这就是它没有初始化的原因。我想了解为什么它使用这种方法而不是MethodHandle反射?

也许还有另一种方法可以在不修改的情况下解决这个问题SomeClass,比如一些编年史配置属性?

4

1 回答 1

1

这似乎是不再支持的版本 2.x 的问题。

在版本 3.x 中,它应该调用默认构造函数(如果存在)。如果没有默认构造函数,它将使用 Unsafe。我添加了一个测试用例,显示这在 3.x 中有效

https://github.com/OpenHFT/Chronicle-Map/blob/master/src/test/java/net/openhft/chronicle/map/externalizable/ExternalizableTest.java

对于 2.x 版本,我建议您需要检查列表是否存在null并根据需要进行设置。

于 2018-06-05T10:36:49.830 回答