Excluding Synthetic Classes in Emma within STS
Asked Answered
I

2

13

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

India answered 15/7, 2013 at 15:41 Comment(2)
The 'hacky' way to ignore the $jacocoData is to know the fact that it is always appended at the end of the class members' list. Though, I would we very interested to know how to exclude any synthetic member of a Java/Scala class.Sainted
Any luck with it? I've come across the same issue and now I'm searching for how to change your code to ignore synthetic members as well.Tenter
I
13

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.

Illtempered answered 12/3, 2015 at 8:43 Comment(0)
D
4

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

for (Field field : fields) {
    if (!field.isSynthetic()) {
        // enter code here
    }
}
Drucilladrucy answered 14/1, 2019 at 5:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.