dex를 실행할 수 없습니다 : [0, 0xffff]에없는 메소드 ID : 65536 것이다. 청소 / 다시

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

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



답변

업데이트 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 팟 캐스트 에피소드 에서 언급되었습니다 . 나는 한 성적 증명서 게시 된 관련 부분 (일반 멀티 덱스 설명).


답변

이미 언급했듯이 프로젝트와 라이브러리에 너무 많은 메소드 (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

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


답변

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


답변

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

답변

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

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

https://github.com/mmin18/Dex65536


답변

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

답변

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

compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
    multiDexEnabled true
}