{"record":{"id":"dac0baba10ee9d8e","repo":"MyCATApache/Mycat-Server","slug":"invalid-final-field-declaringclass-fieldname","errorCode":null,"errorMessage":"Invalid final field ${declaringClass}.${fieldName}","messagePattern":"Invalid final field (.+?)\\.(.+?)","errorType":"exception","errorClass":"ObjectAccessException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/config/util/ReflectionProvider.java","lineNumber":182,"sourceCode":"            ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data));\n            return in.readObject();\n        } catch (IOException e) {\n            throw new ObjectAccessException(\"Cannot create \" + type.getName() + \" by JDK serialization\", e);\n        } catch (ClassNotFoundException e) {\n            throw new ObjectAccessException(\"Cannot find class \" + e.getMessage());\n        }\n    }\n\n    private boolean fieldModifiersSupported(Field field) {\n        return !(Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers()));\n    }\n\n    private void validateFieldAccess(Field field) {\n        if (Modifier.isFinal(field.getModifiers())) {\n            if (JVMInfo.is15()) {\n                field.setAccessible(true);\n            } else {\n                throw new ObjectAccessException(\"Invalid final field \" + field.getDeclaringClass().getName() + \".\"\n                        + field.getName());\n            }\n        }\n    }\n\n    private Object readResolve() {\n        serializedDataCache = Collections.synchronizedMap(new HashMap<Class<?>, byte[]>());\n        fieldDictionary = new FieldDictionary();\n        return this;\n    }\n\n}","sourceCodeStart":164,"sourceCodeEnd":194,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/config/util/ReflectionProvider.java#L164-L194","documentation":"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>'.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Remove the final modifier from the field (or make it non-final for deserialization paths)","Use a constructor-based or setter-based population path instead of field reflection","Add a readResolve/readObject customization in the target class so final fields are set at construction","If you truly run Java 1.5, verify JVMInfo detection is correct (JVMInfo.is15)"],"exampleFix":"// before\nprivate final int port = 8080; // blocks reflection write\n// after\nprivate int port = 8080;","handlingStrategy":"validation","validationCode":"for (Field f : obj.getClass().getDeclaredFields()) {\n    if (Modifier.isFinal(f.getModifiers())) {\n        throw new IllegalStateException(\"final field not writable via reflection: \" + f.getName());\n    }\n}","typeGuard":"boolean nonFinal = (f.getModifiers() & java.lang.reflect.Modifier.FINAL) == 0;","tryCatchPattern":"try {\n    provider.visitSerializableFields(obj, visitor);\n} catch (ObjectAccessException e) {\n    if (e.getMessage().startsWith(\"Invalid final field\")) {\n        // construct the object via constructor instead\n    }\n}","preventionTips":["Don't declare deserialized fields final","Use constructors or readResolve for immutable fields","Audit target classes with a reflection-based test before config-time","Verify JVM version expectations match JVMInfo detection"],"tags":["reflection","final-field","immutable"],"backgroundTag":"unsupported-operation","analyzedSha":"65f8d8beb752f935752f2a0eec0ab017facab9ef","analyzedAt":"2026-09-11T00:12:21.696Z","contentChangedAt":"2026-09-11T00:12:21.696Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}