{"record":{"id":"1605b69dcf7c5782","repo":"alibaba/spring-ai-alibaba","slug":"final-fieldname","errorCode":null,"errorMessage":"无法修改final字段: <fieldName>","messagePattern":"无法修改final字段: <fieldName>","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"spring-boot-starters/spring-ai-alibaba-starter-config-nacos/src/main/java/com/alibaba/cloud/ai/agent/nacos/NacosModelInjector.java","lineNumber":107,"sourceCode":"\n\t/**\n\t * 使用Unsafe修改final字段（适用于Java 12+）\n\t */\n\tprivate static void modifyFinalFieldWithUnsafe(Field field, Object targetObject, Object newValue) throws Exception {\n\t\ttry {\n\t\t\tClass<?> unsafeClass = Class.forName(\"sun.misc.Unsafe\");\n\t\t\tField unsafeInstanceField = unsafeClass.getDeclaredField(\"theUnsafe\");\n\t\t\tunsafeInstanceField.setAccessible(true);\n\t\t\tObject unsafeInstance = unsafeInstanceField.get(null);\n\n\t\t\tMethod putObjectMethod = unsafeClass.getMethod(\"putObject\", Object.class, long.class, Object.class);\n\t\t\tMethod staticFieldOffsetMethod = unsafeClass.getMethod(\"staticFieldOffset\", Field.class);\n\n\t\t\tlong offset = (Long) staticFieldOffsetMethod.invoke(unsafeInstance, field);\n\t\t\tputObjectMethod.invoke(unsafeInstance, targetObject, offset, newValue);\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new RuntimeException(\"无法修改final字段: \" + field.getName(), e);\n\t\t}\n\t}\n}\n","sourceCodeStart":89,"sourceCodeEnd":111,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-boot-starters/spring-ai-alibaba-starter-config-nacos/src/main/java/com/alibaba/cloud/ai/agent/nacos/NacosModelInjector.java#L89-L111","documentation":"NacosModelInjector.modifyFinalFieldWithUnsafe fails to modify a final field of an object through reflection plus an Unsafe internal API, and wraps any failure in a RuntimeException naming the field. This usually means the Unsafe access technique is not viable on the current JVM (method renamed/removed, module access denied) or the target object/field is mismatched.","triggerScenarios":"modifyFinalField called on a field of an object where the Unsafe class lookup, staticFieldOffset invocation, or putObject invocation fails — e.g. on JDK 9+ with strong encapsulation blocking sun.misc.Unsafe internals, or a null targetObject.","commonSituations":"Upgrading to a newer JDK that removes or restricts the internal Unsafe API (the code reflects on method names like staticFieldOffset); running with a Security Manager or JPMS settings blocking reflective access; injecting into record-like/final classes.","solutions":["Read the wrapped cause to see whether it is NoSuchMethodException (JDK removed the API) or IllegalAccessException (module restrictions).","Run the JVM with --add-opens flags for the relevant modules if encapsulation is the blocker.","Prefer designing the target class with a mutable field or constructor injection instead of final-field mutation.","Pin/adjust the JDK version to one supported by NacosModelInjector's Unsafe approach."],"exampleFix":"// before: JVM flags omitted\njava -jar app.jar\n// after: open required modules so Unsafe reflection works\njava --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED -jar app.jar","handlingStrategy":"try-catch","validationCode":"// Detect Unsafe availability on the current JVM before attempting injection\ntry {\n    Class<?> unsafeClass = Class.forName(\"sun.misc.Unsafe\");\n    unsafeClass.getMethod(\"staticFieldOffset\", Field.class);\n} catch (ClassNotFoundException | NoSuchMethodException e) {\n    throw new IllegalStateException(\"Unsafe final-field injection unsupported on this JVM: \" + e.getMessage());\n}","typeGuard":null,"tryCatchPattern":"try {\n    injector.modifyFinalField(target, field, value);\n} catch (RuntimeException e) {\n    logger.error(\"Final field {} not modifiable: {}\", field.getName(), e.getCause(), e);\n    throw new IllegalStateException(\"Configuration injection failed; fix the field design instead\", e);\n}","preventionTips":["Prefer constructor/setter injection over mutating final fields.","Run with --add-opens flags if JPMS blocks the reflective access.","Pin a JDK version known to support the Unsafe internal API used by the injector."],"tags":["reflection","jvm","unsafe","nacos"],"backgroundTag":"incompatible-platform-runtime","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}