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

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

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

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

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

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
  • Весна ДМ
  • JAXBContext инициализируется с помощью ClassLoader пакета, содержащего классы, подлежащие маршаллингу/демаршаллингу.

person Boris Terzic    schedule 18.12.2008    source источник


Ответы (4)


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

JAXBContext.newInstance(MyClass1.class,MyClass2.class, [...]);
person ivan_ivanovich_ivanoff    schedule 22.03.2009

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

@XmlAnyElement(lax = true)
public List<Foo> foos;
person Johan Sjöberg    schedule 10.01.2012

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

synchronized (JAXBContext.class) {
    context = JAXBContext.newInstance(packageList, classLoader);
}
person Boris Terzic    schedule 21.07.2009

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

 private static Unmarshaller um;

  static{
    try {
      final JAXBContext ctx = JAXBContext.newInstance(ObjectFactory.class.getPackage().getName());
      um = ctx.createUnmarshaller();
    } catch (final JAXBException e) {
      e.printStackTrace();
    }
  }
person jon077    schedule 22.02.2011