Jacoco is adding a $jacocoInit method in my interface when running unit tests

hatellla :

I am getting a unnecessary method $jacocoInit when adding the defaut method in interface. My interface looks like this:

@Value.Immutable
public interface Customer {


    Optional<@NotBlank String> name();

    default Object getObject(final String abc) {
        return null
    }

    default void getObject() {

    }
}

When I am doing

for (Method method : Customer.class.getDeclaredMethods()) {
    System.out.println(method.getName());
}

then, I am getting

name
getObject
$jacocoInit

If I remove the default method from it, then it does not $jacocInit method. I am not sure why it is happening? Can someone please help in this?

Godin :

According to JaCoCo FAQ:

To collect execution data JaCoCo instruments the classes under test which adds two members to the classes: A private static field $jacocoData and a private static method $jacocoInit(). Both members are marked as synthetic.

Please change your code to ignore synthetic members. This is a good practice anyways as also the Java compiler creates synthetic members in certain situation.

Method isSynthetic of class java.lang.reflect.Method

Returns true if this executable is a synthetic construct; returns false otherwise.

So to ignore synthetic members:

for (Method method : Customer.class.getDeclaredMethods()) {
    if (method.isSynthetic()) {
        continue;
    }
    System.out.println(method.getName());
}

And here is one of many examples where Java compiler creates synthetic method:

import java.lang.reflect.*;

class Example {

    interface I {
        Runnable r = () -> {}; // lambda

        void m();
    }

    public static void main(String[] args) {
        for (Method method : I.class.getDeclaredMethods()) {
            System.out.println("name: " + method.getName());
            System.out.println("isSynthetic: " + method.isSynthetic());
            System.out.println();
        }
    }
}

Using JDK 1.8.0_152 execution of

javac Example.java
java Example

produces

name: m
isSynthetic: false

name: lambda$static$0
isSynthetic: true

And here is what Java Virtual Machine Specification states about synthetic members:

A class member that does not appear in the source code must be marked using a Synthetic attribute, [...]

You can read more about JaCoCo implementation in its documentation and in presentations done by JaCoCo team, which also include some other examples of synthetic constructions.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326593&siteId=1
Recommended