Как решить проблему с ограничением компилятора Dalvik на методы 64K?

Моя команда и я унаследовали большой проект Android от другой команды. Сообщается, что все приложение со всеми включенными библиотеками имеет около 35000 методов. Теперь у нас есть задача реализовать новый сервис в приложении, где нам нужно использовать протокольные буферы.

Проблема в том, что сгенерированный файл .jar со всеми необходимыми файлами .proto создает еще пару 35000 методов, то есть 70000 методов. И если вы не в курсе, компилятор Android имеет ограничение в 65536 методов на файл .dex. Мы явно превысили этот предел, и при попытке скомпилировать приложение мы получаем следующую ошибку:

Unable to execute dex: method ID not in [0, 0xffff]: 65536
Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536

Да, архитектура приложения, вероятно, должна быть реструктурирована, но это потребует времени. А пока мы пытаемся найти решение, чтобы временно обойти эту проблему.

Какие-либо предложения?


person rfgamaral    schedule 15.03.2013    source источник
comment
На днях команда Facebook опубликовала сообщение именно об этой проблеме. facebook. com/notes/facebook-engineering/   -  person Rawkode    schedule 15.03.2013
comment
Если ваше приложение содержит так много методов (и вы не можете избавиться от некоторых из них), решением, вероятно, будет разделение приложения на более мелкие части, которые могут быть встроены в отдельные файлы dex. Пример см. в этой записи в блоге. как это сделать.   -  person Michael    schedule 15.03.2013
comment
@Rawkode: проблема с Facebook была связана с недостаточным размером буфера LinearAlloc в более старых версиях Android (froyo, пряники). Эталонный предел метода 64 КБ встроен в сами инструкции Dalvik.   -  person fadden    schedule 16.03.2013


Ответы (7)


Вы можете использовать другой файл DEX. Вот как вы это делаете:

http://android-developers.blogspot.co.il/2011/07/custom-class-loading-in-dalvik.html

person Udinic    schedule 16.03.2013
comment
Вот скрипт для подсчета количества методов в каждой банке: /а> - person Tom Susel; 28.07.2014
comment
Связанный пост немного устарел, он показывает, как загрузить несколько файлов DEX в проект на основе Ant. Он также напрямую использует DexClassLoader, что больше не требуется, поскольку android.support.multidex помогает вам в этом и доступен в библиотеке поддержки (редакция 21). Подробное объяснение того, как интегрировать MultiDex в ваше приложение, находится здесь: contentful.com/blog/2014/10/30/ - person woot; 30.10.2014
comment
аналогично сценарию @TomSusel, мы написали небольшой плагин Gradle, который дает вам более глубокое представление о количестве ваших методов и о том, откуда они берутся в каждой сборке — github.com/KeepSafe/dexcount-gradle-plugin - person philipp; 31.07.2015

Включите Proguard (http://developer.android.com/tools/help/proguard.html), чтобы удалить неиспользуемые методы. Генератор protobuf создает тысячи методов, которые на самом деле никогда не используются.

Микропротобуферы (https://code.google.com/p/micro-protobuf/) также могут быть полезным.

person fadden    schedule 15.03.2013
comment
Я изучал использование proguard для этого, но я не уверен, как включить его для сборки конфигурации отладки/запуска в Eclipse. Любые намеки на это? - person rfgamaral; 17.03.2013
comment
В stackoverflow есть несколько полезных сообщений, таких как stackoverflow.com/questions/4732656/ . - person fadden; 17.03.2013
comment
Кажется, я не могу найти ничего по этому вопросу, в котором упоминается использование proguard с конфигурациями отладки/запуска с помощью Eclipse... - person rfgamaral; 17.03.2013

У Square были похожие проблемы, и они создали Wire, чтобы справиться с взрывом метода, вызванным protobufs. Они утверждают, что убили 10 000 методов.

person Abhay Buch    schedule 01.11.2013

В версиях сервисов Google Play до 6.5 вам нужно было скомпилировать весь пакет API в свое приложение. В некоторых случаях это усложняло удержание количества методов в вашем приложении (включая API-интерфейсы фреймворка, библиотечные методы и ваш собственный код) в пределах 65 536.

Начиная с версии 6.5, вместо этого вы можете выборочно скомпилировать сервисные API Google Play в свое приложение. Например, чтобы включить только API Google Fit и Android Wear, замените следующую строку в файле build.gradle:

compile 'com.google.android.gms:play-services:6.5.87'

с этими строками:

compile 'com.google.android.gms:play-services-fitness:6.5.87'
compile 'com.google.android.gms:play-services-wearable:6.5.87'

для получения дополнительной информации вы можете нажать здесь

person akshay    schedule 27.02.2015

Если это первое использование буферов протокола, вы можете посмотреть на альтернативные реализации JavaME, т.е.

есть и другие, перечисленные в дополнениях сторонних производителей. Если вы не использовали ни один из них, но они кажутся меньшими и не имеют всех методов, созданных буферами стандартного протокола.

person Bruce Martin    schedule 15.03.2013

Недавно мы добавили в Android Nano Protobuf, что значительно сокращает количество созданные методы.

person Wink Saville    schedule 18.07.2013
comment
Подробнее, пожалуйста, если позволите? - person icedwater; 18.07.2013
comment
Да, пожалуйста... Подробнее о том, что именно мы должны сделать, чтобы начать использовать Nano Protobufs... - person rfgamaral; 19.07.2013

Если вы используете eclipse, это самый простой обходной путь Нажмите здесь!

person mboy    schedule 11.07.2016