Không thể thực thi dex: ID phương thức không trong [0, 0xffff]: 65536


344

Tôi đã thấy các phiên bản khác nhau của dex erros trước đây, nhưng phiên bản này là mới. làm sạch / khởi động lại, vv sẽ không giúp đỡ. Các dự án thư viện dường như còn nguyên vẹn và sự phụ thuộc dường như được liên kết chính xác.

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

hoặc là

Cannot merge new index 65950 into a non-jumbo instruction

hoặc là

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

tl; dr : Giải pháp chính thức từ Google cuối cùng đã có mặt!

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

Chỉ một mẹo nhỏ, bạn có thể sẽ cần phải làm điều này để ngăn chặn bộ nhớ khi thực hiện dex-ing.

dexOptions {
        javaMaxHeapSize "4g"
}

Ngoài ra còn có một chế độ jumbo có thể khắc phục điều này theo một cách ít đáng tin cậy hơn:

dexOptions {
        jumboMode true
}

Cập nhật: Nếu ứng dụng của bạn béo và bạn có quá nhiều phương pháp trong ứng dụng chính của mình, bạn có thể cần phải tối ưu lại ứng dụng của mình theo

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


1
Bạn có sử dụng api không khả dụng trên thiết bị currient của bạn?
thiệu

Đó là vì dự án khác xây dựng tốt nhắm mục tiêu cùng phiên bản API.
Edison

Vì vậy, bạn sử dụng tại một số điểm API không có sẵn? Bạn có kiểm tra với một dòng như thế if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)mà bạn không gọi chức năng này nếu nó không có sẵn?
thiệu lại

Vâng tôi sẽ làm. Dự án xây dựng tốt trước. Ngoài ra, đó phải là một lỗi thời gian chạy ngay cả khi tôi bỏ lỡ dòng.
Edison

Có lẽ một trong những phụ thuộc đã bị rối tung. (thực hiện kết hợp maven + dự án lib ngay bây giờ)
Edison

Câu trả lời:


379

Cập nhật 3 (11/3/2014)
Google cuối cùng đã phát hành mô tả chính thức .


Cập nhật 2 (31/10/2014)
Gradle plugin v0.14.0 cho Android bổ sung hỗ trợ cho đa dex. Để kích hoạt, bạn chỉ cần khai báo nó trong build.gradle :

android {
   defaultConfig {
      ...
      multiDexEnabled  true
   }
}

Nếu ứng dụng của bạn hỗ trợ Android trước 5.0 (nghĩa là, nếu bạn từ minSdkVersion20 tuổi trở xuống), bạn cũng phải tự động vá ứng dụng ClassLoader , do đó, nó sẽ có thể tải các lớp từ các dex thứ cấp. May mắn thay, có một thư viện làm điều đó cho bạn. Thêm nó vào phụ thuộc của ứng dụng của bạn:

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

Bạn cần gọi mã vá ClassLoader càng sớm càng tốt. tài liệuMultiDexApplication của lớp gợi ý ba cách để làm điều đó (chọn một trong số chúng , một cách thuận tiện nhất cho bạn):

1 - Khai báo MultiDexApplicationlớp dưới dạng ứng dụng trong AndroidManifest.xml của bạn :

<?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 - Yêu cầu Applicationlớp học của bạn mở rộng lớp MultiDexApplication :

public class MyApplication extends MultiDexApplication { .. }

3 - Gọi MultiDex#installtừ Application#attachBaseContextphương thức của bạn :

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

Cập nhật 1 (17/10/2014):
Như dự đoán, hỗ trợ multidex được cung cấp trong phiên bản 21 của Thư viện hỗ trợ Android. Bạn có thể tìm thấy thư mục android-support-multidex.jar trong thư mục / sdk / extend / android / support / multidex / library / libs.


Hỗ trợ đa dex giải quyết vấn đề này. dx 1.8 đã cho phép tạo một số tệp dex.
Android L sẽ hỗ trợ đa dex nguyên bản và thư viện hỗ trợ sửa đổi tiếp theo sẽ bao gồm các bản phát hành cũ hơn trở lại API 4.

Đó là tuyên bố trong này phát triển Android Backstage podcast bởi Anwar Ghuloum. Tôi đã đăng một bảng điểm (và giải thích đa dex chung) của phần có liên quan.


2
bài đăng trên blog là một tiết kiệm! : D
nadavfima

39
Bất cứ điều gì cho người dùng nhật thực?
Muhammad Babar

52
@MuhammadBabar Có studio Android cho người dùng Eclipse.
VipulKumar

2
@MohammedAli Chắc chắn, tránh sử dụng nó nếu bạn có thể. Nhưng bạn nên làm gì nếu bạn thực sự có quá nhiều phương pháp trong ứng dụng của mình và bạn đã thử tất cả các thủ thuật như phương pháp mà bạn đã đề cập? Về thời gian xây dựng - có giải pháp cho việc này, ít nhất là cho các bản dựng phát triển - xem câu trả lời của tôi ở đây: stackoverflow.com/a/30799491/1233652
Alex Lipov

2
Trên Qt cho Android, tôi gặp vấn đề trong thời gian chạy cho ứng dụng của mình khi tích hợp SDK của Facebook + Twitter với nhau, ngay cả sau khi bật hỗ trợ multidex (đặc biệt là lỗi này đã gây cho tôi cơn ác mộng java.lang.ClassNotFoundException: Didn't find class "org.qtproject.qt5.android.QtActivityDelegate" on path: DexPathList[[],nativeLibraryDirectories=[/vendor/lib, /system/lib]]:). Hóa ra, lỗi của tôi là tôi đã không áp dụng các bước bổ sung cho hỗ trợ Android trước 5.0. Như đã nói, tùy chọn # 3 đã giải quyết nó, và tôi không còn ClassNotFoundExceptionvấn đề gì nữa . Cảm ơn, @Alex Lipov!
cướp

78

Như đã nêu, bạn có quá nhiều phương thức (hơn 65k) trong dự án và libs của bạn.

Ngăn chặn sự cố: Giảm số lượng phương thức với Play Services 6.5+ và support-v4 24.2+

Vì thường các dịch vụ Google Play là một trong những nghi phạm chính trong các phương pháp "lãng phí" với các phương thức 20k + của nó . Các dịch vụ Google Play phiên bản 6.5 trở lên, bạn có thể đưa các dịch vụ Google Play vào ứng dụng của mình bằng một số thư viện khách nhỏ hơn. Ví dụ: nếu bạn chỉ cần GCM và bản đồ, bạn có thể chọn chỉ sử dụng các phụ thuộc này:

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

Danh sách đầy đủ các thư viện phụ và trách nhiệm của nó có thể được tìm thấy trong tài liệu google chính thức .

Cập nhật : Vì Thư viện hỗ trợ v4 v24.2.0, nó được chia thành các mô-đun sau:

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

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

Tuy nhiên, xin lưu ý, nếu bạn sử dụng support-fragment, nó sẽ có các phụ thuộc cho tất cả các mô-đun khác (nghĩa là nếu bạn sử dụng android.support.v4.app.Fragmentthì không có lợi ích gì)

Xem ở đây các ghi chú phát hành chính thức cho lib-v4 lib


Kích hoạt tính năng MultiDexing

Vì Lollipop (còn gọi là công cụ xây dựng 21+) nên rất dễ xử lý. Cách tiếp cận là giải quyết 65k phương pháp cho mỗi vấn đề về tệp dex để tạo nhiều tệp dex cho ứng dụng của bạn. Thêm phần sau vào tệp xây dựng lớp của bạn ( phần này được lấy từ tài liệu google chính thức trên các ứng dụng có hơn 65 nghìn phương thức ):

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

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

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

Bước thứ hai là chuẩn bị lớp Ứng dụng của bạn hoặc nếu bạn không mở rộng Ứng dụng, hãy sử dụng MultiDexApplicationBản kê khai Android của bạn:

Thêm cái này vào Application.java của bạn

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

hoặc sử dụng ứng dụng được cung cấp từ lib 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>

Ngăn chặn OutOfMemory với MultiDex

Như một mẹo nữa, nếu bạn gặp phải OutOfMemorytrường hợp ngoại lệ trong giai đoạn xây dựng, bạn có thể phóng to heap bằng

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

mà sẽ đặt heap thành 4 gigabyte.

Xem câu hỏi này để biết thêm chi tiết về vấn đề bộ nhớ hex dex.


Phân tích nguồn gốc của vấn đề

Để phân tích nguồn của các phương thức, plugin gradle https://github.com/KeepSafe/dexcount-gradle-plugin có thể giúp kết hợp với cây phụ thuộc được cung cấp bởi gradle với vd

.\gradlew app:dependencies

Xem câu trả lời và câu hỏi này để biết thêm thông tin về số phương pháp trong Android


Tôi đã sử dụng giải pháp Play Services 6.5+ và nó hoạt động hoàn hảo. Mẹo hữu ích đáng kinh ngạc. Cám ơn rất nhiều!
Hoàng Nguyên Hữu

Tôi sẽ nâng cao hơn nếu tôi có thể - cắt bỏ tất cả những thứ khác của Dịch vụ Play mà chúng tôi không sử dụng đã khắc phục sự cố này mà không phải dùng đến đa dex, điều này có ý nghĩa hiệu quả tiêu cực khi xây dựng.
Sean Barbeau

1
Hơn bạn rất nhiều với nước mắt trong mắt tôi. Bạn đã cứu tôi
mất ngủ

Tôi đã sử dụng thư viện máy khách cho GCM, vì tôi chỉ sử dụng dịch vụ gcm từ dịch vụ chơi, bây giờ nó đã khắc phục vấn đề của tôi với điều này. Cảm ơn! để tiết kiệm thời gian của tôi
Ankit

57

Dự án của bạn quá lớn. Bạn có quá nhiều phương pháp. Chỉ có thể có 65536 phương thức cho mỗi ứng dụng. xem tại đây https://code.google.com.vn/p/android/issues/detail?id=7147#c6


Tôi hiểu rồi. Tôi có rất nhiều phụ thuộc cho dự án này. Nó xây dựng tốt trước khi tôi chuyển sang sử dụng maven, có lẽ maven đã thêm các phụ thuộc không cần thiết. Sẽ kiểm tra lại.
Edison

5
Để cụ thể hơn, chỉ có thể có 65.536 phương thức cho mỗi tệp thực thi (dex) của Dalvik. Và một ứng dụng (APK) có thể có nhiều hơn một tệp dex với những thứ như tải tùy chỉnh.
Dennis Sheil

7
Đó là lỗi thực sự đáng xấu hổ cho Android! Dù sao, trong trường hợp của tôi, tôi đã loại bỏ Jar trong libs và không được sử dụng, và ứng dụng được biên dịch
David

Thời gian để làm sạch dự án của tôi: /
Decoy

1
Một cách khắc phục nhanh là sử dụng Proguard cùng với các bản dựng gỡ lỗi
aleb

12

Các mã dưới đây sẽ giúp, nếu bạn sử dụng Gradle. Cho phép bạn dễ dàng xóa các dịch vụ Google không cần thiết (giả sử bạn đang sử dụng chúng) để quay lại dưới ngưỡng 65k. Tất cả tín dụng cho bài đăng này: https://gist.github.com/dmarcato/d7c91b94214acd936e42

Chỉnh sửa 2014-10-22 : Đã có rất nhiều cuộc thảo luận thú vị về ý chính được tham chiếu ở trên. TLDR? nhìn vào cái này: https://gist.github.com/Takhion/10a37046b9e6d259bb31

Dán mã này vào cuối tệp build.gradle của bạn và điều chỉnh danh sách các dịch vụ google bạn không cần:

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
    }
}

Yêu nó! def cần thiết vì các công ty như Google tiếp tục thổi phồng các gói.
Edison

1
Nice - điều này đã làm công việc trên. Không phức tạp và không phải lo lắng!
slott

Lưu ý: điều này đã xóa các dịch vụ google play trong SDK Android của tôi trong Android Studio! Một ý tưởng tồi vì không dễ để trở lại bình ban đầu. Tác giả nên sửa đổi tập lệnh để thay đổi các tệp trong thư mục xây dựng.
ấn định

@inder: Tôi không có vấn đề đó. Tuy nhiên, tôi đã phải làm cleanmỗi lần tôi bị loại trừ (chúng tôi sử dụng phân tích).
JohnnyLambada

Làm thế nào để loại trừ điều này khỏi các bản dựng phát hành?
user1324936

6

Tôi đã chia sẻ một dự án mẫu giải quyết vấn đề này bằng cách sử dụng tập lệnh xây dựng custom_rules.xml và một vài dòng mã.

Tôi đã sử dụng nó cho dự án của riêng mình và nó chạy hoàn hảo trên các thiết bị 1M + (từ android-8 đến android-19 mới nhất). Hy vọng nó giúp.

https://github.com/mmin18/Dex65536


1
Cảm ơn các kịch bản. bạn nên coi chừng ART. Thiết bị chỉ có thể chuyển đổi dex mặc định của bạn chứ không phải thứ cấp phụ. Giải pháp Proguard nên được ưu tiên.
Edison

2
Khi tôi nhập các dự án vào Eclipse và chạy nó sẽ báo lỗi. "Không thể thực thi dex: ID phương thức không trong [0, 0xffff]: 65536". Bạn có thể khám phá việc sử dụng dự án
Karacago

6

Đối mặt với cùng một vấn đề và giải quyết nó bằng cách chỉnh sửa tệp build.gradle của tôi trên phần phụ thuộc, xóa:

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

Và thay thế nó bằng:

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

Hoàn hảo! Tôi chỉ sử dụng API Google Drive và điều này hoạt động.
vedavis

5

Hãy thử thêm mã dưới đây vào build.gradle, nó hoạt động với tôi -

compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
    multiDexEnabled true
}

2

Giải pháp hoàn hảo cho việc này sẽ là hợp tác với Proguard. như aleb đã đề cập trong bình luận. Nó sẽ giảm kích thước của tệp dex xuống một nửa.


1
Đồng ý, với một dịch vụ google play ngày càng lớn đặc biệt là * (phương thức 18k)
Edison

2

Bạn có thể phân tích vấn đề (tham chiếu tệp dex) bằng Android Studio:

Xây dựng -> Phân tích APK ..

Trên bảng kết quả, nhấp vào tập tin class.dex

Và bạn sẽ thấy:

nhập mô tả hình ảnh ở đây


0

giải pháp 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

Xóa một số tệp jar khỏi thư mục Libs và sao chép vào một số thư mục khác, và Chuyển đến _Project Properties> Chọn Java Build Path, Chọn thư viện, chọn Thêm jar ngoài, chọn jar đã xóa vào dự án của bạn, Nhấp vào lưu, điều này sẽ được thêm vào trong Tài liệu tham khảo Thư viện thay vì thư mục Libs. Bây giờ dọn dẹp và chạy dự án của bạn. Bạn không cần thêm bất kỳ mã nào cho MultDex. Nó chỉ đơn giản là làm việc cho tôi.


0

Tôi đã phải đối mặt với cùng một vấn đề ngày hôm nay những gì làm việc cho bên dưới

Đối với ANDROID STUDIO ... Kích hoạt tính năng chạy ngay lập tức

Trong Tệp-> Tùy chọn-> Xây dựng, Thực thi, Triển khai-> Chạy ngay-> Kiểm tra Bật Chạy ngay lập tức để trao đổi nóng ...

Hy vọng nó giúp


1
Điều này làm việc cho tôi - Tôi chỉ đơn giản là vô hiệu hóa Bật Run, nhấp vào Áp dụng, kích hoạt lại và nó hoạt động trở lại.
MrBigglesworth
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.