Неможливо виконати ідентифікатор dex: методу не в [0, 0xffff]: 65536


344

Раніше я бачив різні версії помилок 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

або

Cannot merge new index 65950 into a non-jumbo instruction

або

java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

tl; dr : Офіційне рішення від Google нарешті тут!

http://developer.android.com/tools/building/multidex.html

Лише одна невелика порада, вам, ймовірно, потрібно буде це зробити, щоб уникнути втрати пам’яті під час декс-інгу.

dexOptions {
        javaMaxHeapSize "4g"
}

Є також джембовий режим, який може виправити це менш надійним способом:

dexOptions {
        jumboMode true
}

Оновлення: Якщо у вашому додатку жир, і у вас є занадто багато методів у вашому головному додатку, можливо, вам доведеться повторно організувати додаток відповідно до

http://blog.osom.info/2014/12/too-many-methods-in-main-dex.html


1
Чи використовуєте ви api, який не є доступним для вашого поточного пристрою?
rekire

Це там, тому що інший проект створює чітку орієнтацію на ту ж версію API.
Едісон

Отже, ви використовуєте в якийсь момент API, який недоступний? Чи перевіряєте ви такою лінією, if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)що ви не викликаєте цю функцію, якщо її немає?
rekire

Так, я. Проект будувався чудово раніше. Також це має бути помилкою виконання, навіть якщо я пропустив рядок.
Едісон

Мабуть, одна із залежностей заплутана. (зараз робимо суміш Maven + Project lib)
Едісон

Відповіді:


379

Оновлення 3 (3.11.2014)
Google нарешті опублікував офіційний опис .


Оновлення 2 (31.10.2014)
плагін Gradle v0.14.0 для Android додає підтримку мультидекса. Щоб увімкнути, потрібно просто оголосити це у build.gradle :

android {
   defaultConfig {
      ...
      multiDexEnabled  true
   }
}

Якщо ваш додаток підтримує Android до 5.0 (тобто якщо вам minSdkVersion20 або менше), вам також доведеться динамічно виправляти додаток ClassLoader , тож він зможе завантажувати класи з вторинних дексі. На щастя, є бібліотека, яка робить це для вас. Додайте його до залежностей свого додатка:

dependencies {
  ...
  compile 'com.android.support:multidex:1.0.0'
} 

Вам потрібно якнайшвидше зателефонувати до патч-коду ClassLoader. ДокументаціяMultiDexApplication класу пропонує три способи зробити це (виберіть один із них , найзручніший для вас):

1 - оголосити MultiDexApplicationклас додатком у AndroidManifest.xml :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.multidex.myapplication">
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
</manifest>

2 - Попросіть ваш Applicationклас розширити клас MultiDexApplication :

public class MyApplication extends MultiDexApplication { .. }

3 - Телефонуйте MultiDex#installзі свого Application#attachBaseContextметоду:

public class MyApplication {
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
        ....
    }
    ....
}

Оновлення 1 (17.10.2014):
Як очікувалося, підтримка мультидекса надається у версії 21 Бібліотеки підтримки Android. Ви можете знайти android-support-multidex.jar у / sdk / extras / android / support / multidex / library / libs.


Підтримка Multi-dex вирішує цю проблему. dx 1.8 вже дозволяє генерувати кілька файлів dex.
Android L підтримуватиме мультидексні програми, і наступна версія бібліотеки підтримки охопить старіші версії назад до API 4.

Про це було сказано в цьому епізоді про подкаст Android Developers Backstage Anwar Ghuloum. Я опублікував стенограму (та загальне мультидекстне пояснення) відповідної частини.


2
повідомлення в блозі - це заощадження! : D
надавфіма

39
Що-небудь для користувачів затемнення?
Мухаммед Бабар

52
@MuhammadBabar Існує Android-студія для користувачів Eclipse.
VipulKumar

2
@MohammedAli Звичайно, уникай його використання, якщо зможеш. Але що робити, якщо у вашому додатку дійсно занадто багато методів, і ви вже випробували всі хитрощі, як той, про який ви згадали? Щодо часу збирання - для цього є рішення, принаймні, для розробок для розвитку - дивіться мою відповідь тут: stackoverflow.com/a/30799491/1233652
Alex Lipov

2
У Qt для Android у мене виникли проблеми під час інтегрування програми для мого додатка, навіть коли було інтегровано SDK-файли Facebook + Twitter разом, навіть після ввімкнення підтримки мультидекса (зокрема ця помилка дала мені кошмари:) java.lang.ClassNotFoundException: Didn't find class "org.qtproject.qt5.android.QtActivityDelegate" on path: DexPathList[[],nativeLibraryDirectories=[/vendor/lib, /system/lib]]. Виявилося, що моя помилка полягала в тому, що я не застосовував додаткові кроки для підтримки Android до 5.0. З урахуванням сказаного, варіант №3 вирішив це, і у мене більше не було ClassNotFoundExceptionпроблем. Дякую, @Alex Lipov!
пограбувати

78

Як уже було сказано, у вас є занадто багато методів (більше 65 к) в своєму проекті.

Запобігання проблемі. Зменшіть кількість методів за допомогою Play Services 6.5+ та support-v4 24.2+

Оскільки часто сервіси Google Play є одним з головних підозрюваних у "витрачанні" методів із її методами 20k + . Служби Google Play версії 6.5 або новішої версії, ви можете включити служби Google Play у свою програму за допомогою декількох менших бібліотек клієнтів. Наприклад, якщо вам потрібні лише GCM та карти, ви можете використовувати лише ці залежності:

dependencies {
    compile 'com.google.android.gms:play-services-base:6.5.+'
    compile 'com.google.android.gms:play-services-maps:6.5.+'
}

Повний перелік під бібліотек та його обов'язки можна знайти в офіційному документі google .

Оновлення : Оскільки Бібліотека підтримки v4 v24.2.0, вона була розділена на наступні модулі:

support-compat, support-core-utils, support-core-ui, support-media-compatІsupport-fragment

dependencies {
    compile 'com.android.support:support-fragment:24.2.+'
}

Однак зауважте, якщо ви використовуєте support-fragment, це матиме залежність від усіх інших модулів (тобто, якщо ви використовуєте, android.support.v4.app.Fragmentнемає ніякої користі)

Дивіться тут офіційні примітки до випуску для support-v4 lib


Увімкнути MultiDexing

Оскільки Lollipop (він же інструменти для збирання 21+) впоратися з ним дуже просто. Підхід полягає в тому, щоб вирішити проблему з методом 65k на файл dex, щоб створити кілька файлів dex для вашої програми. Додайте до файлу збірки gradle наступне ( це взято з офіційного документа google для додатків із більш ніж 65 к методами ):

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.1'
}

Другий крок - або підготувати клас програми, або якщо ви не розширюєте програму, використовуйте на MultiDexApplicationсвоєму Manifest Android:

Або додайте це до свого Application.java

@Override
  protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
  }

або скористайтеся наданою програмою від lili mutlidex

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.myapplication">
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
</manifest>

Запобігання OutOfMemory за допомогою MultiDex

В якості подальшої підказки, якщо ви зіткнетесь з OutOfMemoryвинятками під час фази збірки, ви можете збільшити купу

android {
    ...
    dexOptions {
        javaMaxHeapSize "4g"
    }
}

який би встановив купу до 4 гігабайт.

Дивіться це запитання для більш детальної інформації щодо проблеми пам'яті Dex.


Проаналізуйте джерело проблеми

Щоб проаналізувати джерело методів, плагін gradle https://github.com/KeepSafe/dexcount-gradle-plugin може допомогти в поєднанні з деревом залежностей, наданим gradle з, наприклад,

.\gradlew app:dependencies

Дивіться цю відповідь та питання для отримання додаткової інформації про кількість методів в android


Я використовував рішення Play Services 6.5+ і воно працювало чудово. Неймовірна корисна порада. Дуже дякую!
Hoang Nguyen Huu

Я б подав більше пропозицій, якщо б міг - вирізати всі інші речі Play Services, які ми не використовували, виправили цю проблему, не вдаючись до мультидекса, що має негативні наслідки для продуктивності при побудові.
Шон Барбо

1
Чим ти стільки зі сльозами на очах. Ти врятував мене
безсоння

Я використовував клієнтську бібліотеку для GCM, тому що я використовую лише сервіси gcm з сервісу відтворення, тепер це вирішило мою проблему. Дякую! щоб заощадити свій час.
Анкіт

57

Ваш проект занадто великий. У вас занадто багато методів. На одну заявку може бути лише 65536 методів. дивіться тут https://code.google.com/p/android/isissue/detail?id=7147#c6


Розумію. У мене дуже багато залежностей від цього проекту. Це добре працює, перш ніж я перейшов до використання Maven, хоча, можливо, Maven додав зайві залежності. Повторимо перевірку.
Едісон

5
Щоб бути більш конкретним, на виконуваний (dex) файл Dalvik може бути лише 65 536 методів. І додаток (APK) може мати декілька файлів dex з такими речами, як завантаження на замовлення.
Денніс Шейл

7
Це справді бентежно помилка для андроїда! У будь-якому випадку, у мені випадку я видалив Jar, який був у лійках і не використовувався, і додаток складено
Девід

Час, щоб почистити мій проект: /
Decoy

1
Швидким виправленням буде використання Proguard також із налагодженнями налагодження
aleb

12

Наведений нижче код допоможе, якщо ви використовуєте Gradle. Дозволяє легко видаляти непотрібні служби Google (припускаючи, що ви ними користуєтесь), щоб повернутися нижче порогу 65 к. Вся заслуга в цій публікації: https://gist.github.com/dmarcato/d7c91b94214acd936e42

Редагувати 2014-10-22 : Про суть, про яку згадувалося вище, було багато цікавої дискусії. TLDR? дивіться на це: https://gist.github.com/Takhion/10a37046b9e6d259bb31

Вставте цей код у нижній частині файлу build.gradle та відрегулюйте список служб Google, які вам не потрібні:

def toCamelCase(String string) {
    String result = ""
    string.findAll("[^\\W]+") { String word ->
        result += word.capitalize()
    }
    return result
}

afterEvaluate { project ->
    Configuration runtimeConfiguration = project.configurations.getByName('compile')
    ResolutionResult resolution = runtimeConfiguration.incoming.resolutionResult
    // Forces resolve of configuration
    ModuleVersionIdentifier module = resolution.getAllComponents().find { it.moduleVersion.name.equals("play-services") }.moduleVersion

    String prepareTaskName = "prepare${toCamelCase("${module.group} ${module.name} ${module.version}")}Library"
    File playServiceRootFolder = project.tasks.find { it.name.equals(prepareTaskName) }.explodedDir

    Task stripPlayServices = project.tasks.create(name: 'stripPlayServices', group: "Strip") {
        inputs.files new File(playServiceRootFolder, "classes.jar")
        outputs.dir playServiceRootFolder
        description 'Strip useless packages from Google Play Services library to avoid reaching dex limit'

        doLast {
            copy {
                from(file(new File(playServiceRootFolder, "classes.jar")))
                into(file(playServiceRootFolder))
                rename { fileName ->
                    fileName = "classes_orig.jar"
                }
            }
            tasks.create(name: "stripPlayServices" + module.version, type: Jar) {
                destinationDir = playServiceRootFolder
                archiveName = "classes.jar"
                from(zipTree(new File(playServiceRootFolder, "classes_orig.jar"))) {
                    exclude "com/google/ads/**"
                    exclude "com/google/android/gms/analytics/**"
                    exclude "com/google/android/gms/games/**"
                    exclude "com/google/android/gms/plus/**"
                    exclude "com/google/android/gms/drive/**"
                    exclude "com/google/android/gms/ads/**"
                }
            }.execute()
            delete file(new File(playServiceRootFolder, "classes_orig.jar"))
        }
    }

    project.tasks.findAll { it.name.startsWith('prepare') && it.name.endsWith('Dependencies') }.each { Task task ->
        task.dependsOn stripPlayServices
    }
}

Любіть це! Def потрібні, оскільки такі компанії, як Google, продовжують надувати пакунки.
Едісон

1
Приємно - це було місце роботи. Без клопоту і ніяких турбот!
слот

Примітка. Ця видалена баночка служб Google Play в моїй SDK для Android в Android Studio! Погана ідея, оскільки повернутись до оригінальних баночок непросто. Автор повинен змінити сценарій, щоб змінити банки в каталозі збірки.
індер

@inder: У мене не було такої проблеми. Однак мені довелося робити cleanщоразу, коли я маніпулював виключеннями (ми використовуємо аналітику).
JohnnyLambada

як виключити це з версій версій?
user1324936

6

Я поділився зразковим проектом, який вирішує цю проблему за допомогою сценарію збірки custom_rules.xml та кількох рядків коду.

Я використовував його у власному проекті, і він працює бездоганно на пристроях 1M + (від android-8 до останнього android-19). Сподіваюся, це допомагає.

https://github.com/mmin18/Dex65536


1
Дякуємо за сценарії. ви повинні стежити за АРТ. Пристрій може конвертувати лише ваш декс за замовчуванням, а не вторинний. Слід віддати перевагу прогуардним рішенням.
Едісон

2
Коли я імпортую проекти у Eclipse та запускаю, це дає помилку. "Неможливо виконати ідентифікатор dex: методу не в [0, 0xffff]: 65536". Чи можете ви пояснити використання проекту
Каракаго

6

Зіткнувся з тією ж проблемою і вирішив її, відредагувавши мій файл build.gradle в розділі залежності, видаливши:

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

І замінивши його на:

compile 'com.google.android.gms:play-services-location:7.8.0'
compile 'com.google.android.gms:play-services-analytics:7.8.0' 

Ідеально! Я просто використовую API Google Drive, і це працює.
vedavis

5

Спробуйте додати код нижче в build.gradle, він працював для мене -

compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
    multiDexEnabled true
}

2

Ідеальним рішенням для цього буде робота з Proguard. як алеб згаданий у коментарі. Це зменшить розмір файлу dex вдвічі.


1
Домовились, особливо з все більш масштабним баночкою служб Google Play * (18-ти методів самотужки)
Едісон,

2

Ви можете проаналізувати проблему (посилання на файли dex) за допомогою Android Studio:

Збірка -> Аналіз APK ..

На панелі результатів натисніть файл class.dex

І ви побачите:

введіть тут опис зображення


0

gradle + proguard рішення:

afterEvaluate {
  tasks.each {
    if (it.name.startsWith('proguard')) {
        it.getInJarFilters().each { filter ->
            if (filter && filter['filter']) {
                filter['filter'] = filter['filter'] +
                        ',!.readme' +
                        ',!META-INF/LICENSE' +
                        ',!META-INF/LICENSE.txt' +
                        ',!META-INF/NOTICE' +
                        ',!META-INF/NOTICE.txt' +
                        ',!com/google/android/gms/ads/**' +
                        ',!com/google/android/gms/cast/**' +
                        ',!com/google/android/gms/games/**' +
                        ',!com/google/android/gms/drive/**' +
                        ',!com/google/android/gms/wallet/**' +
                        ',!com/google/android/gms/wearable/**' +
                        ',!com/google/android/gms/plus/**' +
                        ',!com/google/android/gms/topmanager/**'
            }
        }
    }
  }
}

0

Видаліть якийсь файл jar із папки Libs та скопіюйте у якусь іншу папку та перейдіть до _Project Properties> Виберіть Java Build Path, Select Libraries, Select Add External Jar, Select Remoted jar to your project, Click save, це буде додано у розділі Посилання Бібліотека замість папки Libs. Тепер очистіть і запустіть свій проект. Вам не потрібно додавати будь-який код для MultDex. Це просто працювало для мене.


0

Я сьогодні стикався з тим же питанням, над чим працював, - знизу

Для ANDROID STUDIO ... Увімкніть миттєвий запуск

У меню Файл-> Налаштування-> Збірка, виконання, розгортання-> Миттєвий запуск-> Перевірити Увімкнути миттєвий запуск для гарячої заміни ...

Сподіваюся, це допомагає


1
Це працювало для мене - я просто відключив Увімкнути запуск, натиснув Застосувати, повторно ввімкнув його, і він знову працював.
MrBigglesworth
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.