Android Studio (3.2.1) Instant 运行 不适用于 Jacoco 0.8.2?

Android Studio (3.2.1) Instant Run doesn't work with Jacoco 0.8.2?

我使用 Android Studio 3.2.1 创建了一个简单的空 Activity 项目 (Java)。它在 Instant 运行 上编译得很好。

但是,当我将 Jacoco 0.8.2 添加到 class 路径时

dependencies {
    classpath 'com.android.tools.build:gradle:3.2.1'
    classpath 'org.jacoco:org.jacoco.core:0.8.2' //<--Added this
}

编译时出现错误

:app:transformClassesWithInstantRunForDebug 134 ms

禁用即时 运行 就可以了。这是 Jacoco 或 Android sdk 中的错误吗?

已更新错误说明

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:transformClassesWithInstantRunForDebug'.
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:103)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:73)
    at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:59)
    at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:59)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:101)
    at org.gradle.api.internal.tasks.execution.FinalizeInputFilePropertiesTaskExecuter.execute(FinalizeInputFilePropertiesTaskExecuter.java:44)
    at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:91)
    at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:62)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:59)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.run(DefaultTaskGraphExecuter.java:256)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:249)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:238)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:123)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access0(DefaultTaskPlanExecutor.java:79)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.execute(DefaultTaskPlanExecutor.java:104)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.execute(DefaultTaskPlanExecutor.java:98)
    at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:663)
    at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:597)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98)
    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:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.RuntimeException: com.android.build.api.transform.TransformException: java.lang.IllegalStateException: java.lang.IllegalStateException
    at com.android.builder.profile.Recorder$Block.handleException(Recorder.java:55)
    at com.android.builder.profile.ThreadRecorder.record(ThreadRecorder.java:104)
    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:73)
    at org.gradle.api.internal.project.taskfactory.IncrementalTaskAction.doExecute(IncrementalTaskAction.java:50)
    at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39)
    at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.run(ExecuteActionsTaskExecuter.java:124)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:113)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:95)
    ... 33 more
Caused by: com.android.build.api.transform.TransformException: java.lang.IllegalStateException: java.lang.IllegalStateException
    at com.android.build.gradle.internal.transforms.InstantRunTransform.doTransform(InstantRunTransform.java:320)
    at com.android.build.gradle.internal.transforms.InstantRunTransform.transform(InstantRunTransform.java:186)
    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)
    ... 49 more
Caused by: java.lang.IllegalStateException: java.lang.IllegalStateException
    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.android.ide.common.internal.WaitableExecutor.waitForTasksWithQuickFail(WaitableExecutor.java:146)
    at com.android.build.gradle.internal.transforms.InstantRunTransform.doTransform(InstantRunTransform.java:315)
    ... 53 more
Caused by: java.lang.IllegalStateException
    at org.objectweb.asm.tree.analysis.BasicInterpreter.<init>(BasicInterpreter.java:66)
    at com.android.build.gradle.internal.incremental.ConstructorBuilder.<init>(ConstructorBuilder.java:127)
    at com.android.build.gradle.internal.incremental.ConstructorBuilder.build(ConstructorBuilder.java:127)
    at com.android.build.gradle.internal.incremental.IncrementalSupportVisitor.visitMethod(IncrementalSupportVisitor.java:223)
    at org.objectweb.asm.ClassVisitor.visitMethod(ClassVisitor.java:327)
    at org.objectweb.asm.commons.SerialVersionUIDAdder.visitMethod(SerialVersionUIDAdder.java:236)
    at org.objectweb.asm.tree.MethodNode.accept(MethodNode.java:686)
    at org.objectweb.asm.tree.ClassNode.accept(ClassNode.java:436)
    at com.android.build.gradle.internal.incremental.IncrementalVisitor.instrumentClass(IncrementalVisitor.java:365)
    at com.android.build.gradle.internal.transforms.InstantRunTransform.transformToClasses2Format(InstantRunTransform.java:414)
    at com.android.build.gradle.internal.transforms.InstantRunTransform.lambda$doTransform(InstantRunTransform.java:276)
    at com.android.build.gradle.internal.transforms.InstantRunTransform.lambda$null(InstantRunTransform.java:305)
    at java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1424)
    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)

引用我在 https://github.com/jacoco/jacoco/issues/779#issuecomment-434281431 的回答:

As you can see - exception originates from com.android.build.gradle.internal:

Caused by: java.lang.IllegalStateException
  at org.objectweb.asm.tree.analysis.BasicInterpreter.<init>(BasicInterpreter.java:66)
  at com.android.build.gradle.internal.incremental.ConstructorBuilder.<init>(ConstructorBuilder.java:127)
  at com.android.build.gradle.internal.incremental.ConstructorBuilder.build(ConstructorBuilder.java:127)
  at com.android.build.gradle.internal.incremental.IncrementalSupportVisitor.visitMethod(IncrementalSupportVisitor.java:223)
  at org.objectweb.asm.ClassVisitor.visitMethod(ClassVisitor.java:327)
  at org.objectweb.asm.commons.SerialVersionUIDAdder.visitMethod(SerialVersionUIDAdder.java:236)
  at org.objectweb.asm.tree.MethodNode.accept(MethodNode.java:686)
  at org.objectweb.asm.tree.ClassNode.accept(ClassNode.java:436)
  at com.android.build.gradle.internal.incremental.IncrementalVisitor.instrumentClass(IncrementalVisitor.java:365)
  at com.android.build.gradle.internal.transforms.InstantRunTransform.transformToClasses2Format(InstantRunTransform.java:414)
  at com.android.build.gradle.internal.transforms.InstantRunTransform.lambda$doTransform(InstantRunTransform.java:276)
  at com.android.build.gradle.internal.transforms.InstantRunTransform.lambda$null(InstantRunTransform.java:305)

Code of com.android.build.gradle.internal.incremental.ConstructorBuilder.build that causes exception at ConstructorBuilder.java:127:

BasicInterpreter interpreter = new BasicInterpreter() {

which is incorrect according to Javadoc of constructor org.objectweb.asm.tree.analysis.BasicInterpreter that throws exception at BasicInterpreter.java:66:

  /**
   * Constructs a new {@link BasicInterpreter} for the latest ASM API version. <i>Subclasses must
   * not use this constructor</i>. Instead, they must use the {@link #BasicInterpreter(int)}
   * version.
   */
  public BasicInterpreter() {
    super(ASM6);
    if (getClass() != BasicInterpreter.class) {
      throw new IllegalStateException();
    }
  }

Clearly this should be reported to developers of Android SDK - https://developer.android.com/studio/report-bugs.html

One might wonder why exception doesn't happen without last line in

dependencies {
    classpath 'com.android.tools.build:gradle:3.2.1'
    classpath 'org.jacoco:org.jacoco.core:0.8.2'

And the reason is similar to https://github.com/jacoco/jacoco/issues/639#issuecomment-355424756 - multiple ASM versions in classpath:

  • JaCoCo 0.8.2 requires ASM 6.2.1 and org.jacoco:org.jacoco.core:0.8.2 correctly declares dependencies on ASM
  • exception was added in ASM 6.1
  • com.android.build.gradle.internal.incremental.ConstructorBuilder most likely was developed / uses older version of ASM

To avoid such classpath issues, developers of Android SDK can reconsider the way they execute JaCoCo and for example use dedicated ClassLoader.

As a possible workaround you can try to use JaCoCo 0.8.1 that depends on ASM 6.0

作为一种可能的解决方法,您可以尝试使用依赖于 ASM 6.0 的 JaCoCo 0.8.1