Domanda

Stiamo vivendo uno estremamente difficile da rintracciare problema per cui stiamo assistendo ClassCastExceptions a volte quando si cerca di iterare su una lista di oggetti deserializzati. Il bit importante è a volte , dopo un riavvio del particolare codice funziona bene. Questo sembra indicare la direzione di concorrenza / temporizzazione / condizione di competizione. Posso confermare che né il JAXBContext, né le marshaller e unmarshallers vengono utilizzati contemporaneamente. Siamo andati per quanto serializzazione accesso ad essi attraverso il blocco.

Tuttavia, poiché si corre su una piattaforma OSGi in cui i singoli fasci sono sempre inizializzati in modo asincrono attraverso DM primavera può essere che 2 diversi fasci stanno creando il loro JAXBContext allo stesso tempo.

In ogni caso Gradirei qualsiasi puntatori verso una spiegazione per quello che potrebbe causare questi intermittenti ClassCastExceptions. L'intermittenza è importante dal momento che indicano che il codice stesso è normalmente lavorando bene, ma che qualche fattore esterno sembra influenzare il comportamento.

Ecco un esempio specifico di eccezione (nota ho rimosso la compagnia cose specifiche):

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)

Tale metodo in linea 180 è una per () costruire un ciclo su un insieme di oggetti TunnelType all'interno di un oggetto deserializzati (detto deserializzazione funziona bene BTW).

Dato che l'unmarshalling oggetto reale è andato bene, è anche fisicamente possibile per JAXB di lasciare oggetti ElementNSImpl all'interno delle collezioni annidate?

ambiente runtime:

  • JAXB 2.1
  • OSGi
  • Primavera DM
  • Il JAXBContext viene inizializzato con il ClassLoader del fascio contenente le classi siano radunate / deserializzati
È stato utile?

Soluzione 3

Fuori della disperazione ci siamo rivolti alla sincronizzazione sull'oggetto JAXBContext.class, vedendo questo come l'unica residua possibilità per qualche condizione di competizione e almeno noi non sono stati in grado di riprodurre di nuovo la questione. Ecco il codice critica:

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

Altri suggerimenti

ottengo questa eccezione solo quando mi dimentico di dire JAXBContext su ALL per-essere-radunate tipi si potrebbe avere a che fare con.

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

Nessuno dei due approcci suggerito qui ha fatto per me. Tuttavia, questo ha risolto il mio problema

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

La clausola sincronizzato sopra ha risolto il problema anche per me, ma sembra che il contesto non dovrebbe essere una variabile locale. Invece dovrebbe essere una variabile di istanza, o statica. Non ero in grado di refactoring il mio codice come mi piacerebbe che, così invece ho spostato il contesto in un inizializzatore statico, che non è perfetto, ma sembra funzionare:

 private static Unmarshaller um;

  static{
    try {
      final JAXBContext ctx = JAXBContext.newInstance(ObjectFactory.class.getPackage().getName());
      um = ctx.createUnmarshaller();
    } catch (final JAXBException e) {
      e.printStackTrace();
    }
  }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top