MyCATApache/Mycat-Server · error · ObjectAccessException

Invalid final field .

Error message

Invalid final field ${declaringClass}.${fieldName}

What it means

validateFieldAccess rejects writing to or reading serializable fields that are declared final when the runtime JVM is not Java 1.5, since final fields cannot reliably be modified via reflection after Java 5. It throws ObjectAccessException 'Invalid final field <declaringClass>.<fieldName>'.

Solutions

  1. Remove the final modifier from the field (or make it non-final for deserialization paths)
  2. Use a constructor-based or setter-based population path instead of field reflection
  3. Add a readResolve/readObject customization in the target class so final fields are set at construction
  4. If you truly run Java 1.5, verify JVMInfo detection is correct (JVMInfo.is15)

Example fix

// before
private final int port = 8080; // blocks reflection write
// after
private int port = 8080;
Defensive patterns

Strategy: validation

Validate before calling

for (Field f : obj.getClass().getDeclaredFields()) {
    if (Modifier.isFinal(f.getModifiers())) {
        throw new IllegalStateException("final field not writable via reflection: " + f.getName());
    }
}

Type guard

boolean nonFinal = (f.getModifiers() & java.lang.reflect.Modifier.FINAL) == 0;

Try / catch

try {
    provider.visitSerializableFields(obj, visitor);
} catch (ObjectAccessException e) {
    if (e.getMessage().startsWith("Invalid final field")) {
        // construct the object via constructor instead
    }
}

Prevention

When it happens

Trigger: visitSerializableFields or writeField is called on a field whose modifiers include final, and JVMInfo.is15() is false (JVM is not Java 1.5), so instead of setAccessible the exception is thrown.

Common situations: Deserializing into immutable-style classes with final fields; a field was made final in a class refactor; running on modern JDK where the 1.5 workaround no longer applies.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11). Data as JSON: /api/errors/dac0baba10ee9d8e. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/io/mycat/config/util/ReflectionProvider.java:182

            ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data));
            return in.readObject();
        } catch (IOException e) {
            throw new ObjectAccessException("Cannot create " + type.getName() + " by JDK serialization", e);
        } catch (ClassNotFoundException e) {
            throw new ObjectAccessException("Cannot find class " + e.getMessage());
        }
    }

    private boolean fieldModifiersSupported(Field field) {
        return !(Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers()));
    }

    private void validateFieldAccess(Field field) {
        if (Modifier.isFinal(field.getModifiers())) {
            if (JVMInfo.is15()) {
                field.setAccessible(true);
            } else {
                throw new ObjectAccessException("Invalid final field " + field.getDeclaringClass().getName() + "."
                        + field.getName());
            }
        }
    }

    private Object readResolve() {
        serializedDataCache = Collections.synchronizedMap(new HashMap<Class<?>, byte[]>());
        fieldDictionary = new FieldDictionary();
        return this;
    }

}

View on GitHub (pinned to 65f8d8beb7)