Прерывистое исключение ClassCastException из ElementNSImpl в собственный тип во время отмены сопоставления

StackOverflow https://stackoverflow.com/questions/377865

Вопрос

Мы сталкиваемся с чрезвычайно сложной для отслеживания проблемой, когда мы видим ClassCastExceptions иногда при попытке выполнить итерацию по списку немаршированных объектов.Важным моментом является иногда, после перезагрузки конкретный код работает нормально.Это, по-видимому, указывает в направлении состояния параллелизма / синхронизации / гонки.Я могу подтвердить, что ни JAXBContext, ни маршаллеры и демаршаллеры не используются одновременно.Мы зашли так далеко, что сериализовали доступ к ним через блокировку.

Однако, поскольку мы работаем на платформе OSGi, где отдельные пакеты инициализируются асинхронно через Spring DM, может случиться так, что 2 разных пакета создают свой JAXBContext одновременно.

В любом случае я был бы признателен за любые указания на объяснение того, что может вызвать эти прерывистый Исключения ClassCastExceptions.Прерывистые значения важны, поскольку они указывают на то, что сам код обычно работает нормально, но, по-видимому, на поведение влияет какой-то внешний фактор.

Вот конкретный пример исключения (обратите внимание, что я удалил информацию, относящуюся к конкретной компании):

Caused by: java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.ElementNSImpl cannot be cast to com.foobar.TunnelType
    at com.foobar.NetMonitorImpl.getVpnStatus(NetMonitorImpl.java:180)

Этот метод в строке 180 представляет собой конструкцию for(), выполняющую цикл над коллекцией объектов TunnelType внутри немаршалированного объекта (упомянутый демаршалинг отлично работает, КСТАТИ).

Учитывая, что фактический демонтаж объекта прошел нормально, возможно ли JAXB вообще физически оставить объекты ElementNSImpl внутри вложенных коллекций?

Среда выполнения:

  • JAXB 2.1
  • OSGi ( ОСГи )
  • Весенний DM
  • JAXBContext инициализируется с помощью ClassLoader пакета, содержащего классы, подлежащие маршалированию / отмене маршалирования
Это было полезно?

Решение 3

В отчаянии мы обратились к синхронизации на JAXBContext.class возражаю, рассматривая это как единственную оставшуюся возможность для какого-то состояния гонки, и, по крайней мере, мы не смогли воспроизвести эту проблему снова.Вот критический код:

synchronized (JAXBContext.class) {
    context = JAXBContext.newInstance(packageList, classLoader);
}

Другие советы

Я получаю это исключение ТОЛЬКО тогда, когда забываю сообщить JAXBContext обо ВСЕХ сортируемых типах, с которыми он мог иметь дело.

JAXBContext.newInstance(MyClass1.class,MyClass2.class, [...]);

Ни один из предложенных здесь подходов не сделал этого за меня.Однако это решило мою проблему

@XmlAnyElement(lax = true)
public List<Foo> foos;

Приведенное выше предложение synchronized также решило проблему для меня, но, похоже, контекст не должен быть локальной переменной.Вместо этого это должна быть переменная экземпляра или статическая.Я не смог реорганизовать свой код так, как мне хотелось бы, поэтому вместо этого я переместил контекст в статический инициализатор, который не идеален, но, похоже, работает:

 private static Unmarshaller um;

  static{
    try {
      final JAXBContext ctx = JAXBContext.newInstance(ObjectFactory.class.getPackage().getName());
      um = ctx.createUnmarshaller();
    } catch (final JAXBException e) {
      e.printStackTrace();
    }
  }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top