Backend Development 9 min read

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

JD Tech Talk
JD Tech Talk
JD Tech Talk
Debugging JaCoCo‑Induced ClassCastException Caused by Synthetic $jacocoData Field in Java

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.

JavareflectionJaCoCoClassCastExceptionSyntheticFields
JD Tech Talk
Written by

JD Tech Talk

Official JD Tech public account delivering best practices and technology innovation.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.