Настройки оптимизации Proguard: включение слияния классов, трансляции и поля /* в современных API и версиях Proguard
Я долгое время запутывал свои приложения, со следующими настройками, которые я принимал как мантры, потому что они были рекомендациями Google
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
Однако на днях я прокомментировал эту строку по ошибке, приложение построено правильно, и "очевидно" работает. Я провел много тестов и не смог сделать это сбой.
Итак, мне интересно, нужны ли отключенные настройки оптимизации...
- на сегодняшний день Android SDK и последние версии Proguard, я только нацеливаю устройства с Android 4.0.3 и выше (15) и пользуюсь Proguard 5.1.
- и для приложений, которые не занимаются экзотическими материалами, и имеют надлежащим образом написанные
proguard.cfg
инструкции по сохранению соответствующих проблемных классов и т.д.
Большинство ответов, приведенных в этом выпуске, имеют противоречивую информацию и относятся к довольно старым версиям API.
Один за другим:
! Код/упрощение/арифметика
Я нашел обсуждение Группы Google, где они говорят, что simplification/arithmethic
не требуется для SDK после Android Donut. Я предполагаю тогда, я могу безопасно включить эту оптимизацию.
класс!/Присоединяемых/*
Похоже, proguard делает хорошую работу в моих проектах с включенной оптимизацией:
[proguard] Number of vertically merged classes: 296
[proguard] Number of horizontally merged classes: 445
Существуют ли другие побочные эффекты, кроме следов стека? Я имею в виду, что побочные эффекты, связанные с сбоем приложения, а не отладки проблем. Я нашел этот связанный вопрос, но он не уверен, что это безопасно или нет.
! field/* и! code/simplification/cast
Я прочитал в этом вопросе, на который ответил автор ProGuard, что они были включены, чтобы избежать ошибок со старыми версиями Proguard. Так безопасно ли их активировать на Proguard 5.1?
Ответы
Ответ 1
Общие рекомендации: нет гарантии, что оптимизация не будет работать, но всегда есть риск. То, что делают настройки Android proguard по умолчанию, - это обеспечить конфигурацию, которая минимизирует этот риск, поэтому почему они выглядят настолько консервативными для вашей конкретной ситуации.
Включение этих оптимизаций просто означает, что если что-то сработает, вы не можете быть так же уверенны в корневой причине. В общем, шаг proguard имеет менее серьезные гарантии того, какие результаты должны быть относительно входных данных, что является источником недетерминизма в вашей программе. Небольшие изменения в коде могут привести к значительному изменению поведения во время выполнения, и это невозможно узнать, пока вы фактически не запустите программу, в зависимости от вашей конфигурации.
В общем, если вы можете запустить APK, и все это работает - тогда отлично, оптимизация работает для вас. Но они не гарантированы.
Ответ 2
Так безопасно ли их активировать на Proguard [5.1]?
Это шаг с высоким риском, и я могу привести вам пример, где он вызывает проблему.
Мы используем ProGuard 5.2.1, и мы сталкиваемся с ошибкой при обновлении оптимизации field/*
(точнее, field/removal/writeonly
, похоже, вызывает проблему). В нашем коде используется protobuf и включение этой оптимизации приводит к сбою ProGuard с этим сообщением на третьем проходе оптимизации:
Optimizing...
Unexpected error while evaluating instruction:
Class = [com/google/protobuf/FieldSet$1]
Method = [()V]
Instruction = [308] isub
Exception = [java.lang.IllegalArgumentException] (Value "com/google/protobuf/WireFormat$JavaType!" is not an integer value [proguard.evaluation.value.TypedReferenceValue])
Unexpected error while performing partial evaluation:
Class = [com/google/protobuf/FieldSet$1]
Method = [()V]
Exception = [java.lang.IllegalArgumentException] (Value "com/google/protobuf/WireFormat$JavaType!" is not an integer value [proguard.evaluation.value.TypedReferenceValue])
Warning: Exception while processing task java.io.IOException: java.lang.IllegalArgumentException: Value "com/google/protobuf/WireFormat$JavaType!" is not an integer value [proguard.evaluation.value.TypedReferenceValue]
Это означает, что тот факт, что эти оптимизации были отключены на протяжении стольких лет, означает, что они, вероятно, не так хорошо поддерживаются, как другие. К счастью, это было поймано во время компиляции, но повторное включение некоторых из этих оптимизаций (например, горизонтальное объединение классов с помощью class/merging/*
) может легко сломать ваше приложение в определенных версиях/сборках Android, не сообщая должным образом вам "разработчику" (например, он может скомпрометировать dexopts или вообще не установить с помощью VerifyError
).