IllegalArgumentException карта инициализации хроники

Вот кусок кода, который у меня есть

MyValue sampleValue = Values.newHeapInstance(MyValue.class); 

// subsequently set the couple of floats and int i have defined in MyValue interface

ChronicleMap<MyKey, MyValue> cache = ChronicleMapBuilder.of(MyKey.class, MyValue.class)
                .entries(100)
                .averageValue(sampleValue)
                .create();

Когда я делаю это, я получаю ошибку

java.lang.IllegalArgumentException: использование BytesMarshallable и типа значения интерфейса, не поддерживаемого в net.openhft.chronicle.map.ChronicleMapBuilder.averageValue(ChronicleMapBuilder.java:660)

Может ли кто-нибудь помочь мне понять, является ли этот шаблон использования неправильным?

Если я перехожу к созданию MyValue путем реализации конкретного класса, а затем создания нового для него, как показано ниже, это работает:

MyValue sampleValue = new MyValueImpl();

// subsequently set the couple of floats and int i have defined in MyValue interface

ChronicleMap<MyKey, MyValue> cache = ChronicleMapBuilder.of(MyKey.class, MyValue.class)
                .entries(100)
                .averageValue(sampleValue)
                .create();

2 ответа

Причину этого исключения можно найти в источнике:

            if (Serializable.class.isAssignableFrom(valueClass))
                LOG.warn("BytesMarshallable " + valueClass + " will be serialized as Serializable as the value class is an interface");
            else
                throw new IllegalArgumentException("Using BytesMarshallable and an interface value type not supported");
}

Который просто вызывает метод isAssignableFrom класса Class, который проверяет:

Определяет, является ли класс или интерфейс, представленный этим объектом Class, тем же или является суперклассом или суперинтерфейсом класса или интерфейса, представленного указанным параметром Class. Возвращает истину, если так; в противном случае возвращается false. Если этот объект Class представляет примитивный тип, этот метод возвращает true, если указанный параметр Class является именно этим объектом Class; в противном случае возвращается false.

Так что это проверяет, если Serializable Класс представлен valueClass, Так что я понимаю, что ваш MyValue не реализует Serializable интерфейс.

И да, даже комментарий гласит:

Настраивает среднее количество байтов, взятых по сериализованной форме значений

Так что, если я не ошибаюсь, просто позвольте вашему классу значений реализовать Serializable интерфейс, и вы должны быть в порядке. Довольно... запутанное сообщение об исключении, я бы сказал.

Использование Values.newHeapInstance() предполагает, что MyValue это так называемый интерфейс значения. Объекты с определенным значением интерфейса имеют постоянный размер в сериализованной форме. Интерфейсы значений специально поддерживаются ChronicleMap, поэтому вам вообще не нужно настраивать размер значений, как показано в этом примере из учебника:

ChronicleMap<LongValue, Order> orders = ChronicleMap
    .of(LongValue.class, Order.class)
    .name("orders-map")
    .entries(1_000_000)
    .create();

LongValue key = Values.newHeapInstance(LongValue.class);
key.setValue(id);
orders.put(key, order);

Обратите внимание, что нет averageValue() ни звони, ни averageValueSize()ни constantValueSizeBySample(),

Представленное сообщение об ошибке действительно сбивает с толку, тем более что ChronicleMap уже знает, что класс значений является интерфейсом значений, и знает его размер. Не стесняйтесь открыть вопрос в https://github.com/OpenHFT/Chronicle-Map.

Другие вопросы по тегам