В настоящее время у меня есть класс, некоторые поля которого инициализированы в объявлении, например:
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
, как, например, какое-то свойство конфигурации хроники?