java-native-access/jna · error · IllegalStateException

Array fields must be initialized

Error message

Array fields must be initialized

What it means

During size calculation with force=true, a Structure array field that is still null means JNA cannot determine the array length, so the structure's size is unknown. IllegalStateException 'Array fields must be initialized' is thrown instead of deferring the calculation.

Source

Thrown at src/com/sun/jna/Structure.java:1393

                                                   + "' must be an interface");
            }
            if (type.isArray()
                && Structure.class.equals(type.getComponentType())) {
                String msg = "Nested Structure arrays must use a "
                    + "derived Structure type so that the size of "
                    + "the elements can be determined";
                throw new IllegalArgumentException(msg);
            }

            int fieldAlignment = 1;
            if (!Modifier.isPublic(field.getModifiers())) {
                continue;
            }

            Object value = getFieldValue(structField.field);
            if (value == null && type.isArray()) {
                if (force) {
                    throw new IllegalStateException("Array fields must be initialized");
                }
                // can't calculate size yet, defer until later
                return null;
            }
            Class<?> nativeType = type;
            if (NativeMapped.class.isAssignableFrom(type)) {
                NativeMappedConverter tc = NativeMappedConverter.getInstance(type);
                nativeType = tc.nativeType();
                structField.writeConverter = tc;
                structField.readConverter = tc;
                structField.context = new StructureReadContext(this, field);
            }
            else if (typeMapper != null) {
                ToNativeConverter writeConverter = typeMapper.getToNativeConverter(type);
                FromNativeConverter readConverter = typeMapper.getFromNativeConverter(type);
                if (writeConverter != null && readConverter != null) {
                    value = writeConverter.toNative(value,
                                                    new StructureWriteContext(this, structField.field));

View on GitHub (pinned to d036ad9781)

Solutions

  1. Assign every array field a non-null, correctly sized array before calling size()/write()
  2. Call allocateMemory()/ensureAllocated only after array initialization, or initialize fields in the constructor
  3. Use initializeField semantics: set defaults for all array fields in the Structure's no-arg constructor
  4. If arrays are dynamic, reserve a maximum size and track the used length separately

Example fix

// before
class Buf extends Structure {
    public byte[] data;
}
Buf b = new Buf();
b.size(); // data is null
// after
class Buf extends Structure {
    public byte[] data = new byte[64];
}
Defensive patterns

Strategy: validation

Validate before calling

for (Field f : S.class.getFields()) {
    if (f.getType().isArray()) {
        f.setAccessible(true);
        try { if (f.get(s) == null) throw new IllegalStateException("Null array field: " + f); }
        catch (IllegalAccessException e) { throw new IllegalStateException(e); }
    }
}

Try / catch

try {
    s.size();
} catch (IllegalStateException e) {
    if ("Array fields must be initialized".equals(e.getMessage())) {
        s.setData(new byte[expectedLen]); // initialize then retry
        s.size();
    } else throw e;
}

Prevention

When it happens

Trigger: Calling size()/getNativeSize/calculations that force layout while an array field remains null (never assigned), e.g. invoking size(true) or methods that force calculation before initializing array fields.

Common situations: Constructing a Structure and computing its size before assigning array fields; arrays initialized lazily in a constructor that wasn't run; serialization/deserialization flows that leave arrays null; getFieldValue returning null due to access problems.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/11bbc0f2baeb8b59. Report an issue: GitHub.