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();

person AlwaysACoder    schedule 07.01.2019    source источник


Ответы (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, который проверяет:

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

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

И да, даже в комментарии это указано:

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

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

person maio290    schedule 07.01.2019

Использование 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. .

person leventov    schedule 10.01.2019