gradle-android-junit-jacoco-plugin icon indicating copy to clipboard operation
gradle-android-junit-jacoco-plugin copied to clipboard

Plugin fails on OpenJDK 11.0.8 when using includeNoLocationClasses = true

Open BenTilbrook opened this issue 4 years ago • 18 comments
trafficstars

The plugin fails with the below error when running jacocoTestReport, if using OpenJDK 11.0.8 (as included in Android Studio 4.2 RC1), and when includeNoLocationClasses = true (which seemingly is required many common setups in order for coverage to be reported correctly.

Steps

  • Use OpenJDK 11.0.8 by setting JAVA_HOME to $ANDROID_STUDIO_PATH/Contents/jre/jdk/Contents/Home (may vary depending on OS)
  • Extract sample project and CD into it
  • Run ./gradlew jacocoTestReportRelease

Expected

Build succeeds

Actual

Build fails

Error

> Task :app:testReleaseUnitTest FAILED
java.lang.NoClassDefFoundError: jdk/internal/reflect/GeneratedSerializationConstructorAccessor1
        at jdk.internal.reflect.GeneratedSerializationConstructorAccessor1.newInstance(Unknown Source)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
        at java.base/java.io.ObjectStreamClass.newInstance(ObjectStreamClass.java:1092)
        at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2150)
        at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1668)
        at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:482)
        at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:440)
        at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.deserializeWorker(SystemApplicationClassLoaderWorker.java:153)
        at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:121)
        at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
        at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
        at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: java.lang.ClassNotFoundException: jdk.internal.reflect.GeneratedSerializationConstructorAccessor1
        at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
        ... 12 more

Sample project

TestJacoco.zip

Environment

AGP 4.1.2 Plugin version 0.16.0 OpenJDK 11.0.8

openjdk 11.0.8 2020-07-14
OpenJDK Runtime Environment (build 11.0.8+10-b944.6916264)
OpenJDK 64-Bit Server VM (build 11.0.8+10-b944.6916264, mixed mode)

BenTilbrook avatar Apr 22 '21 06:04 BenTilbrook

I face the same issue in circle ci when compile with JDK11, i found that the root cause is this one (https://github.com/gradle/gradle/issues/5184), i tried the solution (jacoco.excludes = ['jdk.internal.*']) it doesn't work, seem like this plugin doesn't expose this field for us to set it externally.

charlesng avatar May 07 '21 07:05 charlesng

the same problem

jiechic avatar May 08 '21 03:05 jiechic

adding this to my script did the trick :

afterEvaluate {
    tasks.withType(Test) {
        jacoco.excludes = ['jdk.internal.*']
    }
}

prolland avatar May 12 '21 10:05 prolland

@prolland Thanks so much for this! I was stuck on this for a while. I had the jacoco.excludes but i wasnt using that inside the afterEvaluate - that is the key! If I understood groovy better I would open a PR to fix this.

im-not-josh avatar May 12 '21 19:05 im-not-josh

Hello, After making this change, I am getting zero coverage in the report. Any inputs here please?

vramasam avatar Jul 09 '21 12:07 vramasam

@vramasam I do have the same problem, but I believe it is due to the upgrade to android gradle plugin 4.2.0 and not jdk11 (both come with the same studio upgrade if I remember well). I had posted a comment here for that and I see there is another comment with a potential workaround. I tried and I now have code coverage again :

  • set jacocoVersion to 0.8.7
  • set testCoverageEnabled to false Don't ask me why ... Maybe some sort of conflict since I think the android gradle plugin has some sort of code coverage support for instrumented tests.

prolland avatar Jul 16 '21 13:07 prolland

@vramasam @prolland Setting testCoverageEnabled to false did the trick for me as well. No idea what's going on here :)

henriquenfaria avatar Jul 19 '21 07:07 henriquenfaria

Hello all, Actually I am not using testCoverageEnabled in my project. It's not required for our project. We are using ./gradlew jacocoTestReportDebug to generate the report.

Here I have not upgraded the Android plugin and I have just upgraded the Java version.

Below are the steps I tired: Step 1: Till now used Java8 , upgrade this to Java11. Step 2: Because of above upgrade got this error (Caused by: java.lang.ClassNotFoundException: jdk.internal.reflect.GeneratedSerializationConstructorAccessor1) Step 3: So used this below code snippet: tasks.withType(Test) { includeNoLocationClasses = true jacoco.excludes = ['jdk.internal.*'] }

After that I am getting coverage report is zero.

vramasam avatar Jul 19 '21 12:07 vramasam

Hello @prolland Any thoughts that would help me here?

vramasam avatar Jul 20 '21 15:07 vramasam

@vramasam No sorry nothing more. Check that you have the testCoverageEnabled set to false in your android config :

buildTypes {
        debug {
            testCoverageEnabled false
            minifyEnabled false
        }
        release {
            signingConfig signingConfigs.release
            testCoverageEnabled false
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

prolland avatar Jul 23 '21 12:07 prolland

@prolland Okay Thank you.

But I am not sure above setting hold good for the AGP 7.0.0. Again it started zero coverage with AGP 7.0.0.

vramasam avatar Jul 29 '21 19:07 vramasam

@prolland Okay Thank you.

But I am not sure above setting hold good for the AGP 7.0.0. Again it started zero coverage with AGP 7.0.0.

I have a possible workaround for you: in my experience switching the Gradle JDK to Adopt OpenJ9 resolves this issue. In Android Studio: open settings > Build, Execution, Deployment > Build Tools > Gradle, change the Gradle JDK to adopt-openj9-11. Might require a reboot.

mrgoltstein avatar Aug 02 '21 14:08 mrgoltstein

Hello @mrgoltstein Thank you for the inputs. But as part of Android Gradle Plugin 7.0.0 , its mandatory to upgrade and use Java 11 for building the Android projects. so we cant downgraded the Java version.

Also, If anyone have a workaround or proper fix with Java 11 and with AGP 7.0.0, please provide the inputs.

vramasam avatar Aug 03 '21 06:08 vramasam

Hello @mrgoltstein Thank you for the inputs. But as part of Android Gradle Plugin 7.0.0 , its mandatory to upgrade and use Java 11 for building the Android projects. so we cant downgraded the Java version.

Also, If anyone have a workaround or proper fix with Java 11 and with AGP 7.0.0, please provide the inputs.

Hi @vramasam I think the name of the SDK might be throwing you off here - adopt-openj9-11 is Java 11. OpenJ9 is the name of the SDK implementation, not an indication of which Java version it is.

mrgoltstein avatar Aug 09 '21 17:08 mrgoltstein

@mrgoltstein Okay Thank you for the explanation. I have tried with OpenJ9 with Android Gradle plugin 7.0.1 but I have no luck, still its shows zero percentage coverage.

vramasam avatar Aug 31 '21 10:08 vramasam

For me, resolving the jdk classes issue required some additional changes in the above snippet. I had to access jacoco.excludes inside of the closure using explicitly specified it.. Otherwise the issue was still present. I also wrapped it with subprojects block. So the whole config looks like (I put it into root project's build.gradle):

junitJacoco {
  includeNoLocationClasses = true
}

subprojects {
  afterEvaluate {
    tasks.withType(Test) {
      // fixes https://github.com/vanniktech/gradle-android-junit-jacoco-plugin/issues/193
      it.jacoco.excludes = ['jdk.internal.*']
    }
  }
}

0neel avatar Dec 23 '21 08:12 0neel

@mrgoltstein The above solution worked finally with latest gradle version. Thank you

vramasam avatar Dec 26 '21 05:12 vramasam

I can't do the same for kotlin DSL jacoco seems to be defined but excludes is not a reference. exclude is in red

tasks.withType<Test>() {
      jacoco.exclude = ["jdk.internal.*"]
  }

grndvl1 avatar Jul 18 '22 20:07 grndvl1