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-compatsupport-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.