MyCATApache/Mycat-Server · error · ObjectAccessException
Cannot create by JDK serialization
Error message
Cannot create ${type} by JDK serialization What it means
instantiateUsingSerialization creates an instance of a type via JDK serialization: it writes an empty instance's serialized form and reads it back to bypass missing constructors. If an IOException occurs during that readObject, the provider throws ObjectAccessException 'Cannot create <type> by JDK serialization'. This usually means the target class is not actually serializable-compatible at that moment or the cached data is corrupt.
Solutions
- Confirm the target class implements Serializable and defines a stable serialVersionUID
- Clear/rebuild the serializedDataCache after upgrading the class
- Ensure the class's no-arg constructor (for Externalizable) does not throw
- If the class cannot be JDK-serialized, provide a working constructor path instead of newInstance-serialization
- Read e.getCause() for the underlying stream/serialization reason
Example fix
// before
class ConfigPoint { private String name; } // no serialVersionUID
// after
class ConfigPoint implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
} Defensive patterns
Strategy: try-catch
Validate before calling
// before instantiation
if (!(Serializable.class.isAssignableFrom(type))) {
throw new IllegalArgumentException(type + " is not Serializable");
}
long svuid = type.getDeclaredField("serialVersionUID").getLong(null); // verify stable UID Try / catch
try {
Object o = provider.newInstance(type);
} catch (ObjectAccessException e) {
// clear cache and retry once
Object o2 = provider.newInstance(type);
} Prevention
- Declare explicit serialVersionUID in all serializable classes
- Invalidate serialized-data caches after class changes
- Ensure class implements Serializable before routing through this path
- Verify no-arg constructors do not throw
When it happens
Trigger: ObjectInputStream.readObject throws IOException because the class's serialized form changed (serialVersionUID mismatch), the class is Externalizable with a failing no-arg constructor, or the cached serialized byte[] is truncated/corrupt.
Common situations: Deserializing a class whose serialVersionUID changed after a library upgrade; class not implementing Serializable but routed through this path; corrupt cached bytes in serializedDataCache.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- No such field .
- Cannot construct as it does not have a no-args constructor
- Cannot construct
- Could not get field .
- Tried to send an out-of-range integer as a 2-byte value
AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11).
Data as JSON: /api/errors/5536cdf02408943b.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/io/mycat/config/util/ReflectionProvider.java:167
DataOutputStream stream = new DataOutputStream(bytes);
stream.writeShort(ObjectStreamConstants.STREAM_MAGIC);
stream.writeShort(ObjectStreamConstants.STREAM_VERSION);
stream.writeByte(ObjectStreamConstants.TC_OBJECT);
stream.writeByte(ObjectStreamConstants.TC_CLASSDESC);
stream.writeUTF(type.getName());
stream.writeLong(ObjectStreamClass.lookup(type).getSerialVersionUID());
stream.writeByte(2); // classDescFlags (2 = Serializable)
stream.writeShort(0); // field count
stream.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA);
stream.writeByte(ObjectStreamConstants.TC_NULL);
data = bytes.toByteArray();
serializedDataCache.put(type, data);
}
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data));
return in.readObject();
} catch (IOException e) {
throw new ObjectAccessException("Cannot create " + type.getName() + " by JDK serialization", e);
} catch (ClassNotFoundException e) {
throw new ObjectAccessException("Cannot find class " + e.getMessage());
}
}
private boolean fieldModifiersSupported(Field field) {
return !(Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers()));
}
private void validateFieldAccess(Field field) {
if (Modifier.isFinal(field.getModifiers())) {
if (JVMInfo.is15()) {
field.setAccessible(true);
} else {
throw new ObjectAccessException("Invalid final field " + field.getDeclaringClass().getName() + "."
+ field.getName());
}
}View on GitHub (pinned to 65f8d8beb7)