Развертывание пользовательского кода Hazelcast с динамически генерируемыми классами

У меня есть приложение, состоящее из сетки узлов hazelcast, в которой используется расширенная генерация байт-кода во время выполнения (asm). В частности, я динамически строю предикат ‹> функций Java из введенных пользователем выражений фильтра. Я хотел бы сохранить предикаты на карте, чтобы они были доступны во всем кластере без необходимости повторной компиляции. Предикаты - не единственный пример этого. У меня также есть классы сопоставления стиля ORM, которые создаются во время выполнения, и их нужно использовать в кластере. Эти классы загружаются настраиваемым загрузчиком классов DynamiClassLoader.

Сначала мне не удавалось хранить свои настраиваемые сгенерированные классы в Hazelcast IMaps, получая ClassNotFoundexception. Однако я обнаружил, что если сообщить Hazelcast использовать мой пользовательский DynamicClassLoader с помощью Config.setClassLoader (), он сможет найти мои динамические классы и использовать их в локальном члене, поэтому у меня нет проблем с сериализацией и десериализацией экземпляров моих пользовательских классов в IMaps в тот же член.

Однако я все еще не могу десериализовать экземпляры моих предикатов, которые были вставлены в карту другим членом. Я включил UserCodeDeployment и прошел через код в моем отладчике, чтобы подтвердить, что, если он не может найти класс локально, он попадает в UserCodeDeploymentClassLoader.java, а в classNotFoundException он проверяет другие члены классов, но не может их найти . Мне не удалось выяснить, как именно это работает. он, кажется, смотрит на внутреннюю карту, для какого члена можно найти любой данный класс, и не находит там мои классы. Я считаю, что он отправляет операцию другим членам, чтобы затем искать класс, но в этом случае похоже, что мой пользовательский загрузчик классов не используется, поэтому он не может найти мои пользовательские классы.

Как я могу заставить динамически сгенерированные классы работать с UserCodeDeployment в Hazelcast? Есть ли способ «зарегистрировать» свои динамические классы с помощью службы кода члена или чего-то подобного?

Спасибо, Трой.


person Troy Peterson    schedule 31.05.2019    source источник
comment
Если копнуть глубже, похоже, что он пытается использовать родительский элемент для ConfigClassLoader: ClassLoader parent = nodeEngine.getConfigClassLoader (). GetParent (); Я не уверен, что это такое ... В javaDoc для getConfigClassLoader написано: Todo: добавить дополнительную документацию, какова цель загрузчика классов конфигурации ... это менее чем полезно. Я не вижу способа это установить.   -  person Troy Peterson    schedule 31.05.2019


Ответы (1)


Я наконец понял это после обширной отладки. Оказывается, операция в Hazelcast для целевого члена по поиску класса вызывает loadBytecodeFromParent () в ClassDataProvider.java. Это ищет файл .class, используя getResourceAsStream в загрузчике классов:

String resource = className.replace('.', '/').concat(".class");

...

is = parent.getResourceAsStream(resource);

Что в основном ищет файл класса в файловой системе. Поскольку мои динамические классы полностью находятся в памяти, для него нет файлового ресурса .class.

Я решил эту проблему, поместив хэш-карту в свой DynamicClassLoader, чтобы сохранить сгенерированный байт-код, и переопределив getResourceAsStream, чтобы вернуть этот байт-код, когда он доступен, прежде чем искать дальше. Теперь это работает!

person Troy Peterson    schedule 31.05.2019