编年史:对象在反序列化期间未初始化
Chronicle: object not initialized during deserialization
我目前有 class,其中一些字段在声明中已初始化,如下所示:
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
}
}
}
而这个 class 用于基于文件的 chronicle-map
配置如下:
ChronicleMap<Long, SomeClass> storage = ChronicleMapBuilder
.of(Long.class, SomeClass.class)
.averageValueSize(avgEntrySize)
.entries(entries)
.createPersistedTo(new File(path));
问题是当我重新启动我的应用程序时,当 chronicle 试图读取保存的地图时我得到 NullpointerException
,因为 hits
字段没有初始化,这意味着它是 null
。
我做了一些调查,发现在调用 readExternal
之前,chronical 使用 UNSAFE.allocateInstance
(in ExternalizableMarshaller
):
创建了这个 class 的对象
protected E getInstance() throws Exception {
return (E) NativeBytes.UNSAFE.allocateInstance(classMarshaled);
}
所以基本上这就是它没有初始化的原因。我想了解为什么它使用这种方法而不是 MethodHandle
或反射?
也许还有另一种方法可以在不修改 SomeClass
的情况下解决这个问题,比如一些编年史配置 属性 也许?
这似乎是不再受支持的版本 2.x 的问题。
在版本 3.x 中,它应该调用默认构造函数(如果存在的话)。如果没有默认构造函数,它将使用 Unsafe。我添加了一个测试用例,它在 3.x
中显示了它的工作原理
对于版本2.x建议您需要查看列表是否为null
,根据需要设置
我目前有 class,其中一些字段在声明中已初始化,如下所示:
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
}
}
}
而这个 class 用于基于文件的 chronicle-map
配置如下:
ChronicleMap<Long, SomeClass> storage = ChronicleMapBuilder
.of(Long.class, SomeClass.class)
.averageValueSize(avgEntrySize)
.entries(entries)
.createPersistedTo(new File(path));
问题是当我重新启动我的应用程序时,当 chronicle 试图读取保存的地图时我得到 NullpointerException
,因为 hits
字段没有初始化,这意味着它是 null
。
我做了一些调查,发现在调用 readExternal
之前,chronical 使用 UNSAFE.allocateInstance
(in ExternalizableMarshaller
):
protected E getInstance() throws Exception {
return (E) NativeBytes.UNSAFE.allocateInstance(classMarshaled);
}
所以基本上这就是它没有初始化的原因。我想了解为什么它使用这种方法而不是 MethodHandle
或反射?
也许还有另一种方法可以在不修改 SomeClass
的情况下解决这个问题,比如一些编年史配置 属性 也许?
这似乎是不再受支持的版本 2.x 的问题。
在版本 3.x 中,它应该调用默认构造函数(如果存在的话)。如果没有默认构造函数,它将使用 Unsafe。我添加了一个测试用例,它在 3.x
中显示了它的工作原理对于版本2.x建议您需要查看列表是否为null
,根据需要设置