R8 仍在堆栈跟踪中,即使它在属性中已关闭

R8 is still in stacktrace even though it is turned off in properties

我正在使用 android 插件 3.4.2,gradle 5.0。我在 gradle.properties android.enableR8 = false

中关闭了 R8

但我仍然得到一个堆栈跟踪,其中 R8 在包中。

这是否意味着 R8 仍然可以正常工作,或者它只是 r8 包中的 dexer?我知道如何修复此错误,但我想确定 R8 是否未启用。

D8: Cannot fit requested classes in the main-dex file (# methods: 65566 > 65536)

java.lang.RuntimeException: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: 
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:593)
        at java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:677)
        at java.util.concurrent.ForkJoinTask.join(ForkJoinTask.java:720)
        at com.google.common.collect.ImmutableList.forEach(ImmutableList.java:407)
        at com.android.build.gradle.internal.transforms.DexMergerTransform.transform(DexMergerTransform.java:244)
        at com.android.build.gradle.internal.pipeline.TransformTask.call(TransformTask.java:239)
        at com.android.build.gradle.internal.pipeline.TransformTask.call(TransformTask.java:235)
        at com.android.builder.profile.ThreadRecorder.record(ThreadRecorder.java:102)
        at com.android.build.gradle.internal.pipeline.TransformTask.transform(TransformTask.java:230)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:103)
        at org.gradle.api.internal.project.taskfactory.IncrementalTaskInputsTaskAction.doExecute(IncrementalTaskInputsTaskAction.java:46)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:41)
        at org.gradle.api.internal.project.taskfactory.AbstractIncrementalTaskAction.execute(AbstractIncrementalTaskAction.java:25)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:28)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.run(ExecuteActionsTaskExecuter.java:401)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:390)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:373)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.access0(ExecuteActionsTaskExecuter.java:79)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.execute(ExecuteActionsTaskExecuter.java:210)
        at org.gradle.internal.execution.steps.ExecuteStep.lambda$execute[=10=](ExecuteStep.java:32)
        at java.util.Optional.map(Optional.java:215)
        at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:32)
        at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:26)
        at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:58)
        at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:35)
        at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:48)
        at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:33)
        at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:39)
        at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:73)
        at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:54)
        at org.gradle.internal.execution.steps.CatchExceptionStep.execute(CatchExceptionStep.java:35)
        at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:51)
        at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:45)
        at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:31)
        at org.gradle.internal.execution.steps.CacheStep.executeWithoutCache(CacheStep.java:201)
        at org.gradle.internal.execution.steps.CacheStep.executeAndStoreInCache(CacheStep.java:183)
        at org.gradle.internal.execution.steps.CacheStep.lambda$executeWithCache(CacheStep.java:106)
        at java.util.Optional.orElseGet(Optional.java:267)
        at org.gradle.internal.execution.steps.CacheStep.lambda$executeWithCache(CacheStep.java:106)
        at org.gradle.internal.Try.apply(Try.java:59)
        at org.gradle.internal.Try.apply(Try.java:56)
        at org.gradle.internal.Try$Success.flatMap(Try.java:102)
        at org.gradle.internal.Try.map(Try.java:56)
        at org.gradle.internal.execution.steps.CacheStep.executeWithCache(CacheStep.java:79)
        at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:69)
        at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:45)
        at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:49)
        at org.gradle.internal.execution.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:43)
        at org.gradle.internal.execution.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:32)
        at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:38)
        at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:24)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:96)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute[=10=](SkipUpToDateStep.java:89)
        at java.util.Optional.map(Optional.java:215)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:54)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:38)
        at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:77)
        at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:37)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:36)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:26)
        at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:90)
        at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:48)
        at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:33)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:117)
        at org.gradle.api.internal.tasks.execution.ResolveBeforeExecutionStateTaskExecuter.execute(ResolveBeforeExecutionStateTaskExecuter.java:75)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:62)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:108)
        at org.gradle.api.internal.tasks.execution.ResolveBeforeExecutionOutputsTaskExecuter.execute(ResolveBeforeExecutionOutputsTaskExecuter.java:67)
        at org.gradle.api.internal.tasks.execution.StartSnapshotTaskInputsBuildOperationTaskExecuter.execute(StartSnapshotTaskInputsBuildOperationTaskExecuter.java:62)
        at org.gradle.api.internal.tasks.execution.ResolveAfterPreviousExecutionStateTaskExecuter.execute(ResolveAfterPreviousExecutionStateTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:94)
        at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:95)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.executeTask(EventFiringTaskExecuter.java:73)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.call(EventFiringTaskExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.call(EventFiringTaskExecuter.java:49)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:49)
        at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:43)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:355)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:343)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:336)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:322)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:134)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:129)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:202)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:193)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:129)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl.run(ManagedExecutorImpl.java:46)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: 
        at java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1431)
        at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
        at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
        at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
        at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: 
        at com.android.builder.dexing.D8DexArchiveMerger.getExceptionToRethrow(D8DexArchiveMerger.java:131)
        at com.android.builder.dexing.D8DexArchiveMerger.mergeDexArchives(D8DexArchiveMerger.java:118)
        at com.android.build.gradle.internal.transforms.DexMergerTransformCallable.call(DexMergerTransformCallable.java:102)
        at com.android.build.gradle.internal.transforms.DexMergerTransformCallable.call(DexMergerTransformCallable.java:37)
        at java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1424)
        ... 4 more
Caused by: com.android.tools.r8.CompilationFailedException: Compilation failed to complete
        at com.android.tools.r8.utils.ExceptionUtils.withCompilationHandler(ExceptionUtils.java:81)
        at com.android.tools.r8.utils.ExceptionUtils.withD8CompilationHandler(ExceptionUtils.java:45)
        at com.android.tools.r8.D8.run(D8.java:94)
        at com.android.builder.dexing.D8DexArchiveMerger.mergeDexArchives(D8DexArchiveMerger.java:116)
        ... 7 more
Caused by: com.android.tools.r8.utils.AbortException: Error: null, Cannot fit requested classes in the main-dex file (# methods: 65566 > 65536)
        at com.android.tools.r8.utils.Reporter.failIfPendingErrors(Reporter.java:101)
        at com.android.tools.r8.utils.Reporter.fatalError(Reporter.java:72)
        at com.android.tools.r8.dex.VirtualFile.throwIfFull(VirtualFile.java:193)
        at com.android.tools.r8.dex.VirtualFile$DistributorBase.fillForMainDexList(VirtualFile.java:328)
        at com.android.tools.r8.dex.VirtualFile$FillFilesDistributor.run(VirtualFile.java:380)
        at com.android.tools.r8.dex.ApplicationWriter.distribute(ApplicationWriter.java:200)
        at com.android.tools.r8.dex.ApplicationWriter.write(ApplicationWriter.java:221)
        at com.android.tools.r8.D8.run(D8.java:215)
        at com.android.tools.r8.D8.lambda$run(D8.java:97)
        at com.android.tools.r8.utils.ExceptionUtils.withCompilationHandler(ExceptionUtils.java:62)
        ... 10 more

Does it mean that R8 somehow still works, or it just dexer in r8 package?

您的堆栈跟踪仅显示 D8 的 类(注意 D8 的 类 驻留在 com.android.tools.r8 包中,这可能会导致混淆)。

您可以通过简单地查找已执行的任务名称来验证是否会调用 D8、D8 with Proguard 或 R8(以下所有测试均使用 AGP 3.4.2 执行)。

android.enableR8=false, minifyEnabled=false => D8

$ ./gradlew assembleRelease --dry-run  
// ... redacted  
:app:transformClassesWithDexBuilderForRelease SKIPPED  
// ... redacted 

android.enableR8=false, minifyEnabled=true => D8 with Proguard

$ ./gradlew assembleRelease --dry-run  
// ... redacted  
:app:transformClassesAndResourcesWithProguardForRelease SKIPPED  
// ... redacted 

android.enableR8=false, minifyEnabled=true, useProguard=false => D8 with Proguard

$ ./gradlew assembleRelease --dry-run  
// ... redacted  
:app:transformClassesAndResourcesWithProguardForRelease SKIPPED  
// ... redacted 

android.enableR8=true, minifyEnabled=true => R8

$ ./gradlew assembleRelease --dry-run  
// ... redacted  
:app:transformClassesAndResourcesWithR8ForRelease SKIPPED  
// ... redacted  

android.enableR8=true, minifyEnabled=true, useProguard=true => R8

$ ./gradlew assembleRelease --dry-run  
// ... redacted  
:app:transformClassesAndResourcesWithR8ForRelease SKIPPED  
// ... redacted 

R8 vs D8 简短回顾

根据 documentation

D8 is a dexer that converts java byte code to dex code.
R8 is a java program shrinking and minification tool that converts java byte code to optimized dex code.

Jake Wharton 更精确的定义:

R8 is a version of D8 that also performs optimization. It’s not a separate tool or codebase, just the same tool operating in a more advanced mode. Where D8 first parses Java bytecode into its own intermediate representation (IR) and then writes out the Dalvik bytecode, R8 adds optimization passes over the IR before its written out.


想要禁用 D8(除了 R8)的人注意事项:

还有用于选择 dx(D8 的前身)的附加标志(参见 this blogpost):
android.enableD8=false

从 AGP 3.1.2 版开始显示以下弃用警告,即使它仍然有效(使用 AGP v3.4.2 测试):

WARNING: The option 'android.enableD8' is deprecated and should not be used anymore.
Use 'android.enableD8=true' to remove this warning.
It will be removed in the future AGP versions. For more details, see https://d.android.com/r/studio-ui/d8-overview.html.