XStream хвърля Exception no-args конструктор на Android

Опитвам се да използвам XStream за (де) сериализиране на HashMap на някои от моите собствени класове в приложение за Android. Например, един от класовете е Word, който има следните променливи:

private String word;
private boolean capitalizable;
private int useCount;
private HashMap<Character,Integer> endPunctuation;
private HashSet<String> nextWritables;

Вече имам цялата настройка, работеща в стандартно java приложение, просто се опитвам да обвия всичко в Android UI (което работи добре). Сериализиране работи добре в Android. Проблемът, който имам, е, че когато десериализирам, получавам следната грешка:

com.thoughtworks.xstream.converters.ConversionException: Cannot construct chatai.Word as it does not have a no-args constructor : Cannot construct chatai.Word as it does not have a no-args constructor 
---- Debugging information ---- 
message             : Cannot construct chatai.Word as it does not have a no-args constructor 
cause-exception     : com.thoughtworks.xstream.converters.reflection.ObjectAccessException 
cause-message       : Cannot construct chatai.Word as it does not have a no-args constructor 
class               : java.util.HashMap 
required-type       : chatai.Word 
path                : /map/entry/chatai.Word 
line number         : 1 
------------------------------- 

Получавам тази грешка, ако използвам която и да е версия на XStream, различна от 1.4.1, в моето настолно приложение. Винаги получавам грешката в приложението си за android, независимо от версията на XStream. Сигурен съм, че настолният има този проблем, защото работи на Java 7. Не съм сигурен за android. Има нещо общо с отражението, поради това предупреждение при добавяне на xstream-1.4.1.jar:

[2011-09-07 21:06:52 - DroidBot] Dx warning: Ignoring InnerClasses attribute for an anonymous inner class 
(com.thoughtworks.xstream.XStream$2) that doesn't come with an 
associated EnclosingMethod attribute. This class was probably produced by a 
compiler that did not target the modern .class file format. The recommended 
solution is to recompile the class from source, using an up-to-date compiler 
and without specifying any "-target" type options. The consequence of ignoring 
this warning is that reflective operations on this class will incorrectly 
indicate that it is *not* an inner class. 

Един бърз тест ми показва, че сериализирането и десериализирането на String обект в Android работи добре. Как мога да се отърва от тази грешка?


person Rahat Ahmed    schedule 08.09.2011    source източник
comment
›com.thoughtworks.xstream.converters.ConversionException: Не може да се конструира chatai.Word, тъй като няма конструктор без аргументи. Класът Word има ли no arg конструктор?   -  person sbridges    schedule 08.09.2011
comment
Не, и не трябва. Не се оплаква в настолното приложение. И мога да прочета сериализирания файл на android и в настолното приложение.   -  person Rahat Ahmed    schedule 09.09.2011
comment
съобщението за грешка изглежда доста ясно, защо иска конструктор по подразбиране?   -  person sbridges    schedule 09.09.2011
comment
Е, някой от пощенския списък ми каза, че ще трябва да прекомпилирам xstream до Java 5 или нещо подобно. Реших просто да използвам вградената сериализация за сега.   -  person Rahat Ahmed    schedule 10.09.2011
comment
Вижте също stackoverflow.com/questions/9621372 / за грешки на конструктор без аргументи, които са били свързани с различни JDK версии, което се отнася повече за настолни машини   -  person OneWorld    schedule 24.10.2014


Отговори (1)


Да, този въпрос е стар, но за любознателния интернет изследовател:

Десериализацията изисква xstream да конструира обект и да зададе всички негови полета на членовете на стойностите, посочени в xml. Ако обектът, който се опитвате да десериализирате, няма конструктор без аргументи, тогава xstream се нуждае от помощ от VM, за да изгради обекта извън нормалния процес на инстанциране и инициализация на обект. Тази помощ е достъпна само в определени виртуални машини; не е наличен под Dalvik VM, когато работи на устройство с Android.

Ако проверите доставчика, който се използва за десериализация на вашия xml, ще откриете, че на вашия работен плот доставчикът вероятно е Sun14ReflectionProvider, който използва специална поддръжка на VM за конструиране на обекти, без да извиква техните конструктори. Под Android доставчикът ще бъде PureJavaReflectionProvider, който не може да десериализира обекти без конструктор без аргументи.

    XStream xstream = new XStream();

    ReflectionProvider rp = xstream.getReflectionProvider();
    if(null != rp)
    {
        System.out.println("Provider class: " + rp.getClass().getName());
        if(rp instanceof Sun14ReflectionProvider)
            System.out.println("Using Sun14ReflectionProvider");
        else if(rp instanceof PureJavaReflectionProvider)
            System.out.println("Using PureJavaReflectionProvider");
    }

В обобщение: Не можете да десериализирате обект без конструктор без аргумент, докато изпълнявате XStream в среда на Android. Ако имате контрол над обекта, преработете го, за да има конструктор без аргументи. Ако нямате контрол над обекта, нямате късмет що се отнася до XStream.

person MikeWeber    schedule 10.01.2014
comment
no-arg конструкторите изглежда се поддържат в по-новите версии на Android, както разбрах в моя малък тест. Тези устройства работеха: CM11 с 4.4.4, устройство на Samsung с 4.3. Тези устройства повдигнаха изключението: устройства на Samsung с 4.2.2 и 4.1.2. Така че наистина е по-безопасно да внедрите конструктори без аргументи И да тествате приложението си на по-старо устройство с Android! - person OneWorld; 24.10.2014
comment
Следвайте моите тестове. Определих доставчиците на отражение с кода на MikeWeber. Моето устройство Samsung с Android 4.3 използва com.thoughtworks.xstream.converters.reflection.SunLimitedUnsafeReflectionProvider, което беше открито като екземпляр на PureJavaReflectionProvider. По-старото устройство на Samsung с Android 4.2.2 използваше само PureJavaReflectionProvider. - person OneWorld; 24.10.2014
comment
Документите към SunLimitedUnsafeReflectionProvid‌​er казват: Създава нов обект, заобикаляйки конструктора, като използва недокументирани вътрешни функции на JDK. (..) се използва като резервен вариант на платформи, които не предоставят пълното ниво на изпълнение за вътрешните елементи (като Dalvik) Вижте също документите на PureJavaReflectionProvider - person OneWorld; 24.10.2014