Десериализация и загрузка классов в Akka - NoClassDefFoundError

Я пытаюсь настроить систему Akka, где ошибки десериализации вызывают протокол, в котором обмениваются отсутствующие классы. Я использую специальный de / serializer для этой цели, который возвращает определенное сообщение субъекту приложения, как только он ловит исключение, связанное с отсутствующими классами.

Проще говоря, удаленная система B отправляет объект в систему A; если во время десериализации система A получает ClassNotFoundError или NoClassDefFoundError, то система A запрашивает у системы B байт-код для неопределенного класса. Когда A получает ответ от B (который представляет собой пару имени класса плюс объект типа Array [Byte]), он может зарегистрировать класс, так что в следующий раз, когда система B отправит объект в систему A, A сможет десериализовать его правильно.

Теперь есть два подхода

1) Система B также отправляет все классы, связанные с запрошенным классом

2) Система B отправляет только байт-код для запрошенного класса (без его зависимостей)

Теперь давайте сосредоточимся на подходе 2 и рассмотрим следующий сценарий

  • 1) B ===obj:X==> A (B отправляет объект класса X в A)
  • 2) Предположим, что X зависит от Y, Z
  • 3) B <==== X? ==== A (A просит класс от X до B)
  • 4) B ===== X ====> B (B предоставляет класс X для A; A регистрирует класс X)
  • 5) B === obj: X ==> A (A получает ошибку из-за отсутствия зависимости Y)
  • 6) B <==== Y? ==== A
  • 7) B ===== Y ====> A (A регистрирует класс Y)
  • 8) B === obj: X ==> A
  • 9) B <==== Z? ==== A
  • 10) B ===== Z ====> A (A регистрирует класс Z)
  • 10) B === obj: X ==> A (ОК, наконец, A может десериализовать объект класса X)

Я думаю, что такой протокол должен работать, но на практике я получаю цикл в шагах 5-7, из-за следующего

NoClassDefFoundError: Lexamples/DemoDecentralizedAkkaPlatformCmdLineMain2$AggregateProgram$$anonfun$main$3$$anonfun$apply$5;

Я получаю, чтобы зарегистрировать следующий класс: examples.DemoDecentralizedAkkaPlatformCmdLineMain2 $ AggregateProgram $$ anonfun $ main $ 3 $$ anonfun $ apply $ 5

однако я продолжаю получать NoClassDefFoundError.

Обратите внимание, что я удаляю начальную букву "L" и завершающий ";" из имени класса, а также заменив "/" на ".". В противном случае я получил бы ошибку в системе B.

Прошу прощения за столь сложную постановку вопроса.

1 ответ

Из абстрактного обзора:

Как только вы получили ошибку "NoClassDefFound Y" для загрузки класса "X", вы гарантированно выбросили загрузчик классов "X" и загрузили "A" в новый загрузчик классов, который включает в себя байтовый код "Y". Если класс get загружен, но не загружается, JVM запоминает ошибку и просто перебрасывает ее. По крайней мере, для некоторых ошибок инициализации класса. Так что вам нужно попробовать перезагрузить в новом загрузчике классов.

Честная рекомендация: если вы пытаетесь создать надежную распределенную систему, не полагайтесь на точный байтовый общий байтовый код и не отправляйте свой байтовый код. Это сделает систему очень хрупкой. В лучшем случае странные ошибки загрузчика классов, ошибки метода не найдены, ошибки сериализации. В худшем случае ваша система запускает невидимый, неожиданный код: как вы развернули новую версию, но она загрузила старый код из все еще работающего другого экземпляра. Используйте некоторую сериализацию, независимую от байтового кода. Выберите один из многих форматов сериализации. Акка приносит уже включенный сериализатор protobuf. И легко включить еще один.

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