dex를 실행할 수 없습니다 : [0, 0xffff]에없는 메소드 ID : 65536


344

나는 이전에 다양한 버전의 덱스 부식을 보았지만 이것은 새로운 것이다. 청소 / 다시 시작 등은 도움이되지 않습니다. 라이브러리 프로젝트는 손상되지 않은 것으로 보이며 종속성이 올바르게 연결된 것 같습니다.

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를 사용합니까?
— 19:47에

다른 프로젝트가 동일한 API 버전을 대상으로 올바르게 빌드하기 때문에 거기에 있습니다.
— Edison

그래서 당신은 사용할 수없는 어떤 시점에서 API를 사용합니까? if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)이 함수를 사용할 수없는 경우이 함수를 호출하지 않는 것과 같은 줄을 확인 합니까?
— rekire

예, 그렇습니다. 프로젝트는 이전에 잘 구축되었습니다. 또한 줄을 놓친 경우에도 런타임 오류가되어야합니다.
— Edison

아마도 종속성 중 하나가 엉망입니다. (현재 maven + project lib를 혼합하여 사용)
— Edison

답변:


379

업데이트 3 (
2014 년 11 월 3 일) Google은 마침내 공식 설명을 발표했습니다 .



Android 용 업데이트 2 ( 2014 년 10 월 31 일 ) Gradle 플러그인 v0.14.0 에는 멀티 덱스 지원 이 추가 되었습니다. 활성화하려면 build.gradle 에 선언해야합니다 .

android {
   defaultConfig {
      ...
      multiDexEnabled  true
   }
}

응용 프로그램이 5.0 이전의 Android를 지원하는 경우 (즉, minSdkVersion20 이하인 경우) 응용 프로그램 ClassLoader 를 동적으로 패치해야 하므로 보조 dexe에서 클래스를로드 할 수 있습니다. 다행히도이를위한 라이브러리 가 있습니다. 앱의 종속성에 추가하십시오.

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

가능한 빨리 ClassLoader 패치 코드를 호출해야합니다. MultiDexApplication클래스의 문서에는 세 가지 방법이 있습니다 ( 가장 편리한 방법 중 하나를 선택 하십시오).

1- AndroidManifest.xmlMultiDexApplication 에서 애플리케이션으로 클래스를 선언 하십시오 .

<?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 ( 2014 년 10 월 17 일 ) :
예상대로 멀티 덱스 지원 은 Android 지원 라이브러리의 개정판 21에 제공됩니다. android-support-multidex.jar은 / sdk / extras / android / support / multidex / library / libs 폴더에 있습니다.


멀티 덱스 지원으로이 문제를 해결합니다. dx 1.8은 이미 여러 dex 파일을 생성 할 수 있습니다.
Android L은 기본적으로 멀티 덱스를 지원하며, 다음 버전의 지원 라이브러리는 이전 릴리스를 API 4로 다시 지원합니다.

Anwar Ghuloum 의이 Android Developers Backstage 팟 캐스트 에피소드 에서 언급되었습니다 . 나는 한 성적 증명서 게시 된 관련 부분 (일반 멀티 덱스 설명).


2
블로그 게시물은 보호기입니다! : D
— nadavfima

39
일식 사용자를위한 것이 있습니까?
— Muhammad Babar

52
@MuhammadBabar Eclipse 사용자를위한 Android 스튜디오가 있습니다.
— VipulKumar

2
@MohammedAli 물론 가능하다면 사용하지 마십시오. 하지만이 경우 어떻게해야 정말 귀하의 응용 프로그램에 너무 많은 방법이 있고, 당신은 이미 언급 한 것과 같은 모든 트릭을 시도? 빌드 시간에 대해서 - 개발 빌드 적어도 위해,이에 대한 해결 방법이 있습니다 - 여기 내 대답을 참조하십시오 stackoverflow.com/a/30799491/1233652
— 알렉스 Lipov

2
Android 용 Qt에서 멀티 덱스 지원을 활성화 한 후에도 Facebook + Twitter의 SDK를 통합 할 때 런타임시 앱에서 문제가 발생했습니다 (이 오류로 인해 악몽이 발생했습니다 :) java.lang.ClassNotFoundException: Didn't find class "org.qtproject.qt5.android.QtActivityDelegate" on path: DexPathList[[],nativeLibraryDirectories=[/vendor/lib, /system/lib]]. 내 실수는 5.0 이전의 Android 지원에 대한 추가 단계를 적용하지 않았다는 것이 밝혀졌습니다. 그 말로, 옵션 # 3이 해결했으며 더 이상 ClassNotFoundException문제 가 없었 습니다. 감사합니다, @Alex Lipov!
— rob

78

이미 언급했듯이 프로젝트와 라이브러리에 너무 많은 메소드 (65k 이상)가 있습니다.

문제 방지 : Play Services 6.5 이상 및 support-v4 24.2 이상으로 방법 수 감소

Google Play 서비스는 종종 20 만 개 이상의 메소드를 사용하여 "낭비하는"메소드의 주요 용의자 중 하나입니다 . 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 doc에서 찾을 수 있습니다 .

업데이트 : Support Library 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의 공식 릴리스 노트를 참조하십시오.


멀티 덱싱 활성화

Lollipop (일명 빌드 도구 21+)이므로 다루기가 매우 쉽습니다. 이 방법은 덱스 파일 당 65k 메서드 문제를 해결하여 앱에 여러 덱스 파일을 만드는 것입니다. gradle 빌드 파일에 다음을 추가하십시오 ( 이는 65k 이상의 메소드가있는 응용 프로그램의 공식 Google 문서에서 가져옵니다 ).

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

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

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

두 번째 단계는 애플리케이션 클래스를 준비하거나 애플리케이션을 확장하지 않는 경우 MultiDexApplicationAndroid Manifest에서를 사용하는 것 입니다.

이것을 Application.java에 추가하십시오.

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

또는 mutlidex lib에서 제공된 응용 프로그램을 사용하십시오.

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

MultiDex로 OutOfMemory 방지

추가 팁으로, OutOfMemory빌드 단계에서 예외가 발생하면 다음을 사용하여 힙을 확대 할 수 있습니다.

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

힙을 4 기가 바이트로 설정합니다.

dex 힙 메모리 문제에 대한 자세한 내용은이 질문을 참조하십시오.


문제의 원인 분석

메소드의 소스를 분석하기 위해 gradle 플러그인 https://github.com/KeepSafe/dexcount-gradle-plugin 은 gradle이 제공하는 종속성 트리와 함께 도움이 될 수 있습니다.

.\gradlew app:dependencies

안드로이드의 메소드 수에 대한 자세한 내용은이 답변과 질문을 참조하십시오


Play 서비스 6.5 이상 솔루션을 사용했으며 완벽하게 작동했습니다. 놀라운 유용한 팁. 정말 고마워!
— Hoang Nguyen Huu

멀티 덱스에 의존하지 않고이 문제를 해결하지 않은 다른 모든 Play 서비스를 잘라낼 수 있다면 더 많은 찬사를 보냈으며, 이는 빌드시 성능에 부정적인 영향을 미칩니다.
— Sean Barbeau

1
내 눈물을 흘리며 너보다 훨씬 당신은 저를 구했습니다
— 불면증

play 서비스에서 gcm 서비스 만 사용하고 있기 때문에 GCM에 클라이언트 라이브러리를 사용했지만 이제는이 문제를 해결했습니다. 감사! 내 시간을 절약하기 위해.
— Ankit

57

프로젝트가 너무 큽니다. 방법이 너무 많습니다. 애플리케이션 당 65536 개의 메소드 만있을 수 있습니다. 여기에서 볼 https://code.google.com/p/android/issues/detail?id=7147#c6


내가 참조. 이 프로젝트에 많은 의존성이 있습니다. 그래도 maven을 사용하기 전에 잘 빌드됩니다 .maven은 불필요한 종속성을 추가했을 수 있습니다. 다시 확인합니다.
— Edison

5
보다 구체적으로, Dalvik 실행 파일 (dex) 파일 당 65,536 개의 메소드 만있을 수 있습니다. 그리고 애플리케이션 (APK)은 커스텀 로딩과 같은 것들을 가진 하나 이상의 dex 파일을 가질 수 있습니다.
— Dennis Sheil

7
정말 안드로이드에 대한 부끄러운 버그입니다! 어쨌든, 필자의 경우 라이브러리에 있었고 사용하지 않은 Jar를 제거하고 응용 프로그램을 컴파일했습니다
— David

내 프로젝트를 정리하는 시간 : /
— Decoy

1
빠른 수정은 디버그 빌드에도 Proguard를 사용하는 것입니다.
— aleb

12

Gradle을 사용하면 아래 코드가 도움이됩니다. 불필요한 Google 서비스 (사용중인 것으로 가정)를 쉽게 제거하여 65k 임계 값 아래로 돌아갈 수 있습니다. 이 게시물에 대한 모든 크레딧 : 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
    }
}

그것을 사랑하십시오! 구글과 같은 회사가 꾸준히 패키지를 부 풀릴 때 필요한 데프.
— 에디슨

1
니스-이것은 일을 시작했다. 번거롭지 않고 걱정할 필요가 없습니다!
— slott

참고 : Android Studio의 Android SDK에서 삭제 된 Google Play 서비스 항아리! 원래 항아리로 되 돌리는 것이 쉽지 않기 때문에 나쁜 생각입니다. 작성자는 빌드 디렉토리에서 jar를 변경하도록 스크립트를 수정해야합니다.
— 인디언 자리

@inder : 나는 그 문제가 없었다. 그러나 clean제외를 사용하여 원숭이를 놀릴 때마다 수행해야했습니다 (분석을 사용합니다).
— JohnnyLambada

이것을 릴리스 빌드에서 제외시키는 방법?
— user1324936

6

custom_rules.xml 빌드 스크립트와 몇 줄의 코드를 사용하여이 문제를 해결하는 샘플 프로젝트를 공유했습니다.

나는 내 자신의 프로젝트에서 그것을 사용했고 1M + 장치에서 완벽하게 실행됩니다 (android-8에서 최신 android-19까지). 도움이 되길 바랍니다.

https://github.com/mmin18/Dex65536


1
스크립트 주셔서 감사합니다. ART를 조심해야합니다. 장치는 기본 덱스 만 변환하고 보조 덱스는 변환 할 수 없습니다. Proguard 솔루션이 선호되어야합니다.
— Edison

2
프로젝트를 Eclipse로 가져 와서 실행할 때 오류가 발생합니다. "dex을 실행할 수 없습니다 : [0, 0xffff]에없는 메소드 ID : 65536" 프로젝트 사용법을
— 설명해 주시겠습니까

6

같은 문제에 직면하고 dependencies 섹션에서 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' 

완전한! Google Drive API를 사용하면 작동합니다.
— vedavis

5

build.gradle에 아래 코드를 추가해보십시오.

compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
    multiDexEnabled true
}

2

이를위한 완벽한 솔루션은 Proguard와 함께 작동하는 것입니다. 코멘트에 언급 된 aleb. 그것은 dex 파일의 크기를 반으로 줄입니다.


1
점점 더 큰 구글 플레이 서비스 병과 특히 합의, * (18k 자체적으로)
— Edison

2

Android Studio를 사용하여 문제점 (dex 파일 참조)을 분석 할 수 있습니다.

빌드-> APK 분석 ..

결과 패널에서 classes.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

Libs 폴더에서 일부 jar 파일을 제거하고 다른 폴더로 복사 한 다음 _Project 속성> Java 빌드 경로 선택, 라이브러리 선택, 외부 Jar 추가 선택, 제거 된 jar을 프로젝트에 선택, 저장을 클릭하십시오. 이것은 참조에 추가됩니다 Libs 폴더 대신 라이브러리. 이제 프로젝트를 정리하고 실행하십시오. MultDex 용 코드를 추가 할 필요가 없습니다. 그것은 단순히 나를 위해 일했습니다.


0

나는 오늘 같은 문제에 직면했다.

ANDROID STUDIO의 경우 ... 인스턴트 실행 사용

File-> Preferences-> Build, Execution, Deployment-> Instant Run-> Hot swap에 대해 Instant run 사용 ...을 선택하십시오.

그것이 도움이되기를 바랍니다.


1
이것은 나를 위해 일했습니다-단순히 Enable Run을 비활성화하고 Apply를 클릭 한 다음 다시 활성화하면 다시 작동합니다.
— MrBigglesworth
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.