vanniktech/gradle-android-junit-jacoco-plugin

Plugin fails on OpenJDK 11.0.8 when using includeNoLocationClasses = true

BenTilbrook opened this issue ยท 18 comments

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)

I face the same issue in circle ci when compile with JDK11, i found that the root cause is this one (gradle/gradle#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.

the same problem

adding this to my script did the trick :

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

@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.

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

@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.

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

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.

Hello @prolland Any thoughts that would help me here?

@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 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.

@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.

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.

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

0neel commented

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.*']
    }
  }
}

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

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.*"]
  }