Debugging JaCoCo‑Induced ClassCastException Caused by Synthetic $jacocoData Field in Java
The article explains how integrating JaCoCo introduced a synthetic boolean array field ($jacocoData) that caused a ClassCastException during object encryption, analyzes the root cause by inspecting bytecode and reflection, and provides a fix by filtering synthetic fields using isSynthetic().
Problem Description – After adding JaCoCo to a Java project, the application started normally but threw a java.lang.ClassCastException: [Z cannot be cast to [Ljava.lang.Object; during order processing, blocking the workflow. The stack trace pointed to the encryptObject method where an object was cast to Object[] .
Analysis
1. Error Code – The exception occurs because the method attempts to iterate over an object assumed to be an array of Object . The type "[Z" represents a boolean array in Java bytecode, which appears after JaCoCo instrumentation adds a synthetic field $jacocoData of type boolean[] .
2. Root Cause Path – The recursive encryptObject method processes collections and arrays. When it encounters the synthetic boolean array, the cast to Object[] fails, leading to the exception. The helper method getDeclaredFieldsAll returns all fields, including synthetic ones, so the synthetic field is inadvertently processed.
3. Synthetic Fields & JaCoCo – Java compilers generate synthetic fields/methods (e.g., $jacocoData ) to support features like inner‑class access. JaCoCo uses ASM to insert probe booleans into a synthetic array, which is not part of the business model.
public void encryptObject(Object obj, String type) throws IllegalAccessException {
// ...
if (clazz.isArray()) {
for (Object o : (Object[]) obj) { // <-- ClassCastException here when obj is boolean[]
this.encryptObject(o, type);
}
}
// ...
}Solution – Filter out synthetic fields before processing them. Using Field.isSynthetic() removes the JaCoCo‑added $jacocoData field, preventing the faulty cast.
List
fieldsList = Arrays.stream(declaredFields)
.filter(field -> !field.isSynthetic())
.collect(Collectors.toList());After applying this change and redeploying with JaCoCo enabled, the order‑processing flow works correctly.
Conclusion – The article documents a real‑world debugging case where JaCoCo instrumentation introduced a synthetic boolean array that broke reflection‑based encryption logic. Understanding compiler‑generated synthetic members and guarding against them (e.g., via isSynthetic() ) improves tool robustness and prevents similar runtime failures.
JD Tech Talk
Official JD Tech public account delivering best practices and technology innovation.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.