Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Excluding Synthetic Classes in Emma within STS

When trying to run Coverage as or run a maven build using emma:emma I get the following:

java.lang.IllegalStateException: Could not access method: Can not set static final [Z field packageName.ClassName.$jacocoData to [Z

So I searched around online and I found the following on the EclEmma website:

My code uses reflection. Why does it fail when I execute it with JaCoCo?

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.

But I cannot find any documentation on the web on how to actually ignore synthetic members with Emma.

In STS I look under Preferences/Java/Code Coverage and I see an Excludes box to put exclusions (and I know I could also put the exclusion in my POM).

I am just wondering what needs to go in there to exclude all synthetic classes.

Thanks

like image 689
bhcmoney Avatar asked Jul 15 '13 15:07

bhcmoney


2 Answers

I think the best way to ignore Synthetic Members is as below;

for (Field field : fields) {
    if (!field.isSynthetic()) {
        // enter code here
    }
}
like image 130
JR Sahoo.'JS' Avatar answered Nov 13 '22 18:11

JR Sahoo.'JS'


I recently ran into this issue with a generic CSV export helper that I was using. The exception you are seeing is that Jacoco/Emma can't set the synthetic field that it uses to track your code coverage. You need to allow Emma to access that synthetic field.

If you have stopped Emma accessing synthetic fields because adding the synthetic field was causing problems with your reflection, eg. you are using reflection to iterate over a collection of Field objects, just do the following:

Field[] fields = fooObject.getClass().getDeclaredFields();
Field[] nonSyntheticFields = new Field[fields.length];

for(int i = 0; i < fields.length; i++){         
    if(!fields[i].isSynthetic()){
        nonSyntheticFields[i] = fields[i];
        //Or whatever processing you are doing here with your fields.
    }
}

The above allows you to separate out synthetic fields, which your application shouldn't really know anything about, from the fields that you have declared on your classes. I know it seems a bit hacky, but it's the most elegant solution that I could come up with. Emma needs that field to be able to instrument your code, the best thing you can do is make sure your code doesn't mess with that synthetic variable.

like image 45
JamesENL Avatar answered Nov 13 '22 20:11

JamesENL