Intermittent ClassCastException من ElementNSImpl لامتلاك النوع أثناء إلغاء التنظيم

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

سؤال

نحن نواجه مشكلة يصعب للغاية تعقبها حيث نشاهد ClassCastExceptions أحيانا عند محاولة التكرار على قائمة الكائنات غير المنظمة.الشيء المهم هو أحيانا, ، بعد إعادة التشغيل، يعمل الكود المعين بشكل جيد.يبدو أن هذا يشير إلى اتجاه حالة التزامن/التوقيت/السباق.أستطيع أن أؤكد أنه لا يتم استخدام JAXBContext ولا المنظمين وunmarshallers بشكل متزامن.لقد ذهبنا إلى حد إجراء تسلسل الوصول إليها من خلال القفل.

ومع ذلك، نظرًا لأننا نعمل على منصة OSGi حيث تتم تهيئة الحزم الفردية بشكل غير متزامن من خلال Spring DM، فمن الممكن أن تقوم حزمتان مختلفتان بإنشاء JAXBContext الخاصة بهما في نفس الوقت.

على أية حال، سأكون ممتنًا لأي تلميحات حول تفسير لما يمكن أن يسبب هذه المشكلة متقطع استثناءات ClassCast.يعتبر المتقطع مهمًا لأنه يشير إلى أن الكود نفسه يعمل عادةً بشكل جيد ولكن يبدو أن بعض العوامل الخارجية تؤثر على السلوك.

فيما يلي مثال محدد للاستثناء (لاحظ أنني قمت بإزالة العناصر الخاصة بالشركة):

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 داخل المجموعات المتداخلة؟

بيئة التشغيل:

  • جاكسب 2.1
  • OSGi
  • ربيع مارك ألماني
  • تتم تهيئة 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;

لقد حلت الجملة المتزامنة أعلاه المشكلة بالنسبة لي أيضًا، ولكن يبدو أن السياق لا ينبغي أن يكون متغيرًا محليًا.بدلاً من ذلك، يجب أن يكون متغير مثيل، أو ثابتًا.لم أتمكن من إعادة بناء الكود الخاص بي بالطريقة التي أريدها، لذا بدلاً من ذلك قمت بنقل السياق إلى مُهيئ ثابت، وهو ليس مثاليًا، ولكن يبدو أنه يعمل:

 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