{"record":{"id":"4e442c192e1bf7fe","repo":"java-native-access/jna","slug":"this-vm-does-not-support-structures-with-final-fields-field","errorCode":null,"errorMessage":"This VM does not support Structures with final fields (field '\" + field.getName() + \"' within \" + getClass() + \")","messagePattern":"This VM does not support Structures with final fields \\(field '\" \\+ field\\.getName\\(\\) \\+ \"' within \" \\+ getClass\\(\\) \\+ \"\\)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"src/com/sun/jna/Structure.java","lineNumber":680,"sourceCode":"     * @param field field to set\n     * @param value value to set\n     */\n    void setFieldValue(Field field, Object value) {\n        setFieldValue(field, value, false);\n    }\n\n    private void setFieldValue(Field field, Object value, boolean overrideFinal) {\n\n        try {\n            field.set(this, value);\n        }\n        catch(IllegalAccessException e) {\n            int modifiers = field.getModifiers();\n            if (Modifier.isFinal(modifiers)) {\n                if (overrideFinal) {\n                    // WARNING: setAccessible(true) on J2ME does *not* allow\n                    // overwriting of a final field.\n                    throw new UnsupportedOperationException(\"This VM does not support Structures with final fields (field '\" + field.getName() + \"' within \" + getClass() + \")\", e);\n                }\n                throw new UnsupportedOperationException(\"Attempt to write to read-only field '\" + field.getName() + \"' within \" + getClass(), e);\n            }\n            throw new Error(\"Unexpectedly unable to write to field '\" + field.getName() + \"' within \" + getClass(), e);\n        }\n    }\n\n    /** Only keep the original structure if its native address is unchanged.\n     * Otherwise replace it with a new object.\n     * @param type Structure subclass\n     * @param s Original Structure object\n     * @param address the native <code>struct *</code>\n     * @return Updated <code>Structure.ByReference</code> object\n     */\n    static <T extends Structure> T updateStructureByReference(Class<T> type, T s, Pointer address) {\n        if (address == null) {\n            s = null;\n        }","sourceCodeStart":662,"sourceCodeEnd":698,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/src/com/sun/jna/Structure.java#L662-L698","documentation":"Thrown when Structure.setFieldValue tries to write a final field, overrideFinal is requested, and the VM still refuses (setAccessible(true) cannot make final fields writable on some VMs, notably J2ME). JNA reports that this VM does not support Structures with final fields.","triggerScenarios":"Declaring a Java field final in a Structure subclass and letting JNA read native memory into it on a VM that cannot override final fields even with setAccessible(true); calling writeField(name, value) on a final field where override applies.","commonSituations":"Porting JNA-based code to J2ME/Embedded JVMs; code that works on HotSpot but fails on constrained VMs; legacy structures with final fields after JVM security tightening.","solutions":["Remove the final modifier from the Structure field","Mark the field volatile or keep it plain so JNA can write it during read()/writeField()","If the value is meant to be constant, use a static final constant outside the structure layout instead of an instance final field","Run on a standard JVM (HotSpot/OpenJ9) that supports final-field override via setAccessible"],"exampleFix":"// before\npublic final int code;\n// after\npublic int code;","handlingStrategy":"type-guard","validationCode":"static boolean isFinalWritable(java.lang.reflect.Field f) {\n    int m = f.getModifiers();\n    return !java.lang.reflect.Modifier.isFinal(m);\n}","typeGuard":"if (java.lang.reflect.Modifier.isFinal(field.getModifiers())) {\n    throw new IllegalStateException(\"JNA cannot write final field on this VM: \" + field.getName());\n}","tryCatchPattern":"try { struct.writeField(name, value); } catch (UnsupportedOperationException e) { /* final field on this VM */ throw new IllegalArgumentException(\"Make field non-final: \" + name, e); }","preventionTips":["Never mark Structure instance fields final","Verify VM support for final-field override before porting to J2ME/embedded JVMs","Use static final constants for truly immutable values (outside layout)","Prefer standard HotSpot/OpenJ9 runtimes"],"tags":["reflection","jna","final-field","vm-compatibility"],"backgroundTag":"unsupported-platform","analyzedSha":"d036ad9781adad4b66693e8fa7098e4ac665e0a3","analyzedAt":"2026-09-12T06:50:59.239Z","contentChangedAt":"2026-09-12T06:50:59.239Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}