Исправляем VerifyError в Android-приложениях с библиотекой Gson

IT-копирайтер
Время чтения: 3 минуты
Одно из наших последних Android-приложений при падении возвращало довольно странную ошибку:
…
Caused by: java.lang.VerifyError:
com.*.logic.ws.WebServiceHelper
…
Возникала ошибка всего у нескольких пользователей, но проигнорировать ее мы, конечно, не могли. Как оказалось, причина скрывалась в том, то некоторые производители телефонов — процент небольшой, но все же — включают библиотеку Gson в ОС устройства. В результате, при использовании данной библиотеки в приложении, возникал конфликт одинаковых классов в classpath.
Если вы столкнулись с подобной проблемой или только начинаете разрабатывать приложение с использованием библиотеки Gson, мы рекомендуем пропатчить локальную версию библиотеки, задав уникальные пути для классов библиотеки, и ваше приложение будет стабильно работать на большем числе устройств. Но обо всем по порядку.
Поиск проблемы
Обычно причину подобной проблемы можно легко найти в логах LogCat, но сообщения об ошибке были получены с Google Play, поэтому в нашем распоряжении оказалась только малоинформативная трассировка стека, по которой можно было только понять, что ошибка java.lang.VerifyError произошла в неком классе, вызываемом из класса WebServiceHelper.
Обычно ошибка java.lang.VerifyError возникает, когда во время выполнения программы JVM понимает, что вызываемый метод на самом деле не существует или не совпадают сигнатуры вызываемого и реального методов. Например, вызов метода String.isEmpty() приведет к возникновению этой ошибки на устройствах с версией Android 2.2 и ниже, так как впервые этот метод был добавлен лишь в 9 версии API.
Поэтому перед выпуском приложения на рынок всегда необходимо тестировать его на минимальной поддерживаемой версии API, указанной в манифесте в атрибуте android:minSdkVersion. Кроме того, такие некорректные вызовы API легко находит Android Lint. Однако в нашем случае никаких некорректных вызовов Android API не было, да и сам класс WebServiceHelper был достаточно простым. Единственным местом, которое могло привести к подобной ошибке, была строка
return new Gson().fromJson(response, responseClass);
Решение
Изучив ресурсы по запросу «Android Gson VerifyError», мы выяснили, что на некоторых устройствах — в основном HTC — библиотека Gson уже присутствует в classpath, и, вместо того, чтобы использовать собственную библиотеку, приложение обращается к версии библиотеки, установленной на устройстве. Версии библиотек, конечно, не совпадают, что и приводит к ошибке.
В одной из веток обсуждения был предложен вариант пропатчить локальную версию библиотеки, изменив название пакета с «com.google.gson» на «com.google.myjson», с помощью программы Jar Jar List. Им мы и воспользовались.
Итак, чтобы исправить ошибку, необходимо выполнить следующее:
- Загрузить приложение Jar Jar List.
- Поместить jarjar-1.3.jar и google-gson-1.6.jar в одну папку.
- Создать в этой папке новый текстовый файл rules.txt.
- Записать в него следующую строку rule com.google.gson.** com.google.myjson.@1.
- Из командной строки запустить команду «java -jar jarjar-1.3.jar process rules.txt google-gson-1.6.jar google-gson-1.6-patched.jar».
- Заменить старую Gson-библиотеку на новую и поправить все импорты в классах.
Описанным методом мы рекомендуем воспользоваться тем, кто, разрабатывая Android-приложения, использует библиотеку Gson — приложение будет работать более стабильно. Проверено.
Комментарии