我现在有一个类,它在声明中初始化了一些字段,如下所示:
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。
我做了一些调查,发现在调用readExternal之前,使用UNSAFE.allocateInstance(在ExternalizableMarshaller中)创建该类的对象:
protected E getInstance() throws Exception {
return (E) NativeBytes.UNSAFE.allocateInstance(classMarshaled);
}所以基本上这就是为什么它没有初始化。我想要理解的是为什么它使用这样的方法而不是MethodHandle或反射?
也许还有另一种方法可以在不修改SomeClass的情况下修复这个问题,比如某些编年史配置属性?
发布于 2018-06-05 10:36:49
这似乎是版本2.x的一个问题,该版本不再受支持。
在3.x版本中,如果存在默认构造函数,则应调用该构造函数。如果没有默认构造函数,它将使用不安全的。我添加了一个测试用例,它在3.x中显示了这一点。
对于2.x版本,我建议您检查列表是否为null,并根据需要设置它。
https://stackoverflow.com/questions/50697300
复制相似问题