🐡

Shrinker Java Bytecodeのバグ対処法【Flutter / Dart / Android】

2021/10/02に公開

はじめまして、ますみです!

株式会社Galirage(ガリレージ)という「生成AIのシステム開発会社」で、代表をしております^^

自己紹介.png

FlutterでのiOS開発を進めている中、ある日Androidのビルドをしたところ、Shrinker Java Bytecodeのエラーにつまづいてしまいました。
flutter runflutter build bundleflutter build apkflutter build appbundleなどのandroidのビルドをする際に最初につまづく部分だと思います。
そこで、この記事では、このエラーの対処法を解説します。

エラー内容

main_error
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:mergeDexDebug'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
   > com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives:
     The number of method references in a .dex file cannot exceed 64K.
     Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 8s
[!] The shrinker may have failed to optimize the Java bytecode.
    To disable the shrinker, pass the `--no-shrink` flag to this command.
    To learn more, see: https://developer.android.com/studio/build/shrink-code
Exception: Gradle task assembleDebug failed with exit code 1
エラー全文はこちら
error_all
D8: Cannot fit requested classes in a single dex file (# methods: 89373 > 65536)
com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives:
The number of method references in a .dex file cannot exceed 64K.
Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html
 at com.android.builder.dexing.D8DexArchiveMerger.getExceptionToRethrow(D8DexArchiveMerger.java:132)
 at com.android.builder.dexing.D8DexArchiveMerger.mergeDexArchives(D8DexArchiveMerger.java:119)
 at com.android.build.gradle.internal.transforms.DexMergerTransformCallable.call(DexMergerTransformCallable.java:102)
 at com.android.build.gradle.internal.tasks.DexMergingTaskRunnable.run(DexMergingTask.kt:432)
 at com.android.build.gradle.internal.tasks.Workers$ActionFacade.run(Workers.kt:242)
 at org.gradle.workers.internal.AdapterWorkAction.execute(AdapterWorkAction.java:57)
 at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
 at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:67)
 at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:63)
 at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:97)
 at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:63)
 at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
 at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
 at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:200)
 at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:195)
 at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
 at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
 at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:153)
 at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:68)
 at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:62)
 at org.gradle.internal.operations.DefaultBuildOperationExecutor.lambda$call$2(DefaultBuildOperationExecutor.java:76)
 at org.gradle.internal.operations.UnmanagedBuildOperationWrapper.callWithUnmanagedSupport(UnmanagedBuildOperationWrapper.java:54)
 at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:76)
 at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
 at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:60)
 at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$2(DefaultWorkerExecutor.java:200)
 at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
 at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:215)
 at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164)
 at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:131)
 at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
 at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
 at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
 at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
 at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
 at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
 at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
 at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: com.android.tools.r8.CompilationFailedException: Compilation failed to complete, position: null
 at Version.fakeStackEntry(Version_2.1.62.java:0)
 at com.android.tools.r8.utils.Y.a(SourceFile:78)
 at com.android.tools.r8.D8.run(D8.java:11)
 at com.android.builder.dexing.D8DexArchiveMerger.mergeDexArchives(D8DexArchiveMerger.java:117)
 ... 36 more
Caused by: com.android.tools.r8.utils.b: Cannot fit requested classes in a single dex file (# methods: 89373 > 65536)
 at com.android.tools.r8.utils.T0.error(SourceFile:1)
 at com.android.tools.r8.utils.T0.a(SourceFile:2)
 at com.android.tools.r8.dex.P.a(SourceFile:740)
 at com.android.tools.r8.dex.P$h.a(SourceFile:7)
 at com.android.tools.r8.dex.b.a(SourceFile:14)
 at com.android.tools.r8.dex.b.b(SourceFile:25)
 at com.android.tools.r8.D8.d(D8.java:133)
 at com.android.tools.r8.D8.b(D8.java:1)
 at com.android.tools.r8.utils.Y.a(SourceFile:36)
 ... 38 more


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:mergeDexDebug'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
   > com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives:
     The number of method references in a .dex file cannot exceed 64K.
     Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 8s
[!] The shrinker may have failed to optimize the Java bytecode.
    To disable the shrinker, pass the `--no-shrink` flag to this command.
    To learn more, see: https://developer.android.com/studio/build/shrink-code
Exception: Gradle task assembleDebug failed with exit code 1
  • このエラーは簡単にいうと「ビルド時の中間ファイルを最適化するときに生じているバグ」です。

対処法

  • minSdkVersionをバージョンを上げると直りました。
  • もしもここをどうしても変えたくない場合は、flutter run --no-shrinkというオプションをつけてもいいですが、minSdkVersion: 16は2012年のJELLY_BEANの時代のものなため、さすがにリガシーバージョンと捉えて、deprecated(非推奨バージョン)として良いと思います(ここはチームの開発指針次第)。
  • 私は、Android 5.0(sdkVersion: 21、LOLLIPOP、2015年)が一つのメジャーアップデートの区切れ目なので、そこまで引き上げることを推奨します(下記コード参照)。
android/app/build.gradle
defaultConfig {
    // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
    applicationId "dev.umimori.sample"
-   minSdkVersion 16
+   minSdkVersion 21
    targetSdkVersion 30
    versionCode flutterVersionCode.toInteger()
    versionName flutterVersionName
}
  • APIレベル表も参考として載せておきます。

https://developer.android.com/guide/topics/manifest/uses-sdk-element?hl=ja#ApiLevels

最後に

最後まで読んでくださり、ありがとうございました!
この記事を通して、少しでもあなたの学びに役立てば幸いです!

おまけ①:生成AIエンジニア塾

より専門的な「生成AIエンジニア人材」を目指しませんか?

そんな方々に向けて、「生成AIエンジニア塾」というプログラムを始めました🎉

最終的なゴールとして、『エンタープライズ向けの生成AIシステムを構築するためのスキルを習得し、大手案件で活躍できる人材』を目標とします。

また、一人一人にしっかりと向き合って、メンタリングをできるようにするため、現在メンバーの人数制限をしております。本気度やスキルレベルの高い人から、順番にご案内しております。

▼ 登録はこちらから ▼
https://bit.ly/generative_ai_engineer_school_by_zenn

おまけ②:AI Newsletter for Biz

最新のAIニュースの情報を収集しませんか?

AI Newsltter for Bizは、ビジネスパーソン向けに「AIニュース」を定期配信する完全無料のニュースレターです📩

一人でも多くの方にとって、「AI人材としてのスキルアップ」につながれば幸いです^^

また、現在、登録者限定で「明日から使える 無料AIサービス3選」のPDFを配布中です 🎁
※ ご登録完了のメールに、PDFリンクを添付いたします。

期間限定のプレゼントとなりますので、ぜひ、お早めにご登録ください!

▼ 登録はこちらから ▼
https://bit.ly/ai_newsletter_for_biz_zenn

Discussion