XStream выдает конструктор исключений без аргументов на 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 (который отлично работает). Сериализация отлично работает в 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 конструктор без аргументов?   -  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 нуждается в помощи виртуальной машины для создания объекта вне обычного процесса создания и инициализации объекта. Эта справка доступна только для определенных ВМ; он недоступен в 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
Конструкторы без аргументов, похоже, поддерживаются в новых версиях 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