java-native-access/jna · error · IllegalArgumentException
This VM does not support read-only fields (field '" + field.
Error message
This VM does not support read-only fields (field '" + field.getName() + "' within " + getClass() + ")
What it means
JNA must write through Structure fields to synchronize them with native memory. On VMs where final (read-only) fields cannot be set reflectively (Platform.RO_FIELDS == false), a final field inside a Structure is unusable, so IllegalArgumentException is thrown naming the field and Structure class.
Source
Thrown at src/com/sun/jna/Structure.java:1360
LayoutInfo info = new LayoutInfo();
info.alignType = this.alignType;
info.typeMapper = this.typeMapper;
boolean firstField = true;
for (Iterator<Field> i=fields.iterator();i.hasNext();firstField=false) {
Field field = i.next();
int modifiers = field.getModifiers();
Class<?> type = field.getType();
if (type.isArray()) {
info.variable = true;
}
StructField structField = new StructField();
structField.isVolatile = Modifier.isVolatile(modifiers);
structField.isReadOnly = Modifier.isFinal(modifiers);
if (structField.isReadOnly) {
if (!Platform.RO_FIELDS) {
throw new IllegalArgumentException("This VM does not support read-only fields (field '"
+ field.getName() + "' within " + getClass() + ")");
}
// In J2SE VMs, this allows overriding the value of final
// fields
field.setAccessible(true);
}
structField.field = field;
structField.name = field.getName();
structField.type = type;
// Check for illegal field types
if (Callback.class.isAssignableFrom(type) && !type.isInterface()) {
throw new IllegalArgumentException("Structure Callback field '"
+ field.getName()
+ "' must be an interface");
}
if (type.isArray()
&& Structure.class.equals(type.getComponentType())) {View on GitHub (pinned to d036ad9781)
Solutions
- Remove the final modifier from the Structure field
- Make the field non-final and, if immutability is desired, enforce it in application code instead
- Upgrade/verify the JNA platform support; on standard J2SE VMs RO_FIELDS is true and final fields are made accessible
- Ensure no SecurityManager/restrictions block field.setAccessible(true) for final fields
Example fix
// before
class S extends Structure {
public final int count; // read-only field
}
// after
class S extends Structure {
public int count;
} Defensive patterns
Strategy: type-guard
Validate before calling
for (Field f : S.class.getFields()) {
if (Modifier.isFinal(f.getModifiers()) && !Platform.RO_FIELDS) {
throw new IllegalStateException("final field not supported: " + f);
}
} Type guard
static boolean isWritableField(Field f) {
int m = f.getModifiers();
return !Modifier.isFinal(m) || Platform.RO_FIELDS;
} Try / catch
try {
s.size();
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("read-only fields")) {
throw new IllegalStateException("Remove final modifier: " + e.getMessage(), e);
}
throw e;
} Prevention
- Never declare final Structure fields
- Check Platform.RO_FIELDS when targeting unusual VMs
- Enforce immutability at the application layer, not via final on native-mapped fields
- Lint for final fields in Structure subclasses
When it happens
Trigger: Declaring a Structure field as final on a VM/platform whose configuration disallows read-only fields (Platform.RO_FIELDS false), causing StructureFieldInfo/derivation to reject the field.
Common situations: Defining public final fields in Structure subclasses by Java habit; running JNA on limited/embedded VMs or security-managed environments where setting accessible final fields is blocked.
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
- This VM does not support Structures with final fields (field
- Attempt to write to read-only field '" + field.getName() + "
- Exception reading field '" + f.getName() + "' in " + getClas
- Can't determine size of nested structure
- Can't instantiate " + type
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/3ee443b687445e9e.
Report an issue: GitHub.