-
Bug
-
Resolution: Duplicate
-
P4
-
20
-
generic
-
generic
ADDITIONAL SYSTEM INFORMATION :
java version "20" 2023-03-21
Java(TM) SE Runtime Environment (build 20+36-2344)
Java HotSpot(TM) 64-Bit Server VM (build 20+36-2344, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
In a specific condition, I cannot unserialize an object that has references to a List created with List.copyOf().
I have this exception while unserializing an object:
java.lang.ClassCastException: cannot assign instance of java.util.CollSer to field a.b.c.BaseClass.aField of type java.util.List in instance of a.b.c.SubClass.
At serialization, the a.b.c.BaseClass.aField does contain a List that was created like this
return List.copyOf(originalList);
I have a “simple” workaround to fix the problem by changing the previous line to:
return originalList.
Note that the list may be shared by multiple instances of a.b.c.BaseClass.
see also:
https://stackoverflow.com/questions/75804762/classcastexception-when-unserializing-an-immutable-list-cannot-assign-instance
https://stackoverflow.com/questions/65613929/map-in-activemq-objectmessage-throws-classcastexception-cannot-assign-instance
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
I can reproduce this problem systematically. Unfortunately, this is a huge object being serialized (215 classes, 900MB on disk, error stack trace is 4200 lines). This object has been growing for years. It uses unmodifiable Maps, Lists, Sets ... all over without problems. It is just à this one usage point added recently where using List.copyOf() method causes this exception. I have tried to reproduce this problem using a small test case unsuccessfully.
Here is the code and state at the point of exception:
If I break and debug at the exception point (this is JDK 17 code) at java.base/java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2227)
private void setObjFieldValues(Object obj, Object[] vals, boolean dryRun) {
if (obj == null) {
throw new NullPointerException();
}
for (int i = numPrimFields; i < fields.length; i++) {
long key = writeKeys[i];
if (key == Unsafe.INVALID_FIELD_OFFSET) {
continue; // discard value
}
switch (typeCodes[i]) {
case 'L', '[' -> {
Object val = vals[offsets[i]];
if (val != null &&
!types[i - numPrimFields].isInstance(val))
{
Field f = fields[i].getField();
throw new ClassCastException(
"cannot assign instance of " +
val.getClass().getName() + " to field " +
f.getDeclaringClass().getName() + "." +
f.getName() + " of type " +
f.getType().getName() + " in instance of " +
obj.getClass().getName());
}
if (!dryRun)
unsafe.putReference(obj, key, val);
}
default -> throw new InternalError();
}
}
}
In my scenario,
obj is an instance of a.b.c.SubClass
vals has 26 elements of which index 17 is a CollSer
dryRun is true
The “i” value is 20.
typecode[i] is ‘L’
numPrimFields is 3
offset[i] is 17
types[i - numPrimFields] is java.util.List
val is a CollSer (array null, tag 1 (IMM_LIST))
The line:
!types[i - numPrimFields].isInstance(val)
Fails because java.util.List is not an instance of java.util.CollSer I think (not sure) CollSer should probably have already been replaced by a List by CollSer’s readResolve() method.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No Exception
ACTUAL -
Caused by: java.lang.ClassCastException: cannot assign instance of java.util.CollSer to field a.b.c.BaseClass.aField of type java.util.List in instance of a.b.c.SubClass.
at java.base/java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2227)
at java.base/java.io.ObjectStreamClass$FieldReflector.checkObjectFieldValueTypes(ObjectStreamClass.java:2191)
at java.base/java.io.ObjectStreamClass.checkObjFieldValueTypes(ObjectStreamClass.java:1478)
at java.base/java.io.ObjectInputStream$FieldValues.defaultCheckFieldValues(ObjectInputStream.java:2657)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2471)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2242)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1742)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:514)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:472)
… 4200 other lines
CUSTOMER SUBMITTED WORKAROUND :
Note that I have used Unmodifiable Maps Lists ... all over this code without problems. It is just à this one usage point where using List.copyOf() method causes this exception at unserialisation time. Using the original modifiable List prevents the exception from being thrown.
FREQUENCY : rarely
java version "20" 2023-03-21
Java(TM) SE Runtime Environment (build 20+36-2344)
Java HotSpot(TM) 64-Bit Server VM (build 20+36-2344, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
In a specific condition, I cannot unserialize an object that has references to a List created with List.copyOf().
I have this exception while unserializing an object:
java.lang.ClassCastException: cannot assign instance of java.util.CollSer to field a.b.c.BaseClass.aField of type java.util.List in instance of a.b.c.SubClass.
At serialization, the a.b.c.BaseClass.aField does contain a List that was created like this
return List.copyOf(originalList);
I have a “simple” workaround to fix the problem by changing the previous line to:
return originalList.
Note that the list may be shared by multiple instances of a.b.c.BaseClass.
see also:
https://stackoverflow.com/questions/75804762/classcastexception-when-unserializing-an-immutable-list-cannot-assign-instance
https://stackoverflow.com/questions/65613929/map-in-activemq-objectmessage-throws-classcastexception-cannot-assign-instance
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
I can reproduce this problem systematically. Unfortunately, this is a huge object being serialized (215 classes, 900MB on disk, error stack trace is 4200 lines). This object has been growing for years. It uses unmodifiable Maps, Lists, Sets ... all over without problems. It is just à this one usage point added recently where using List.copyOf() method causes this exception. I have tried to reproduce this problem using a small test case unsuccessfully.
Here is the code and state at the point of exception:
If I break and debug at the exception point (this is JDK 17 code) at java.base/java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2227)
private void setObjFieldValues(Object obj, Object[] vals, boolean dryRun) {
if (obj == null) {
throw new NullPointerException();
}
for (int i = numPrimFields; i < fields.length; i++) {
long key = writeKeys[i];
if (key == Unsafe.INVALID_FIELD_OFFSET) {
continue; // discard value
}
switch (typeCodes[i]) {
case 'L', '[' -> {
Object val = vals[offsets[i]];
if (val != null &&
!types[i - numPrimFields].isInstance(val))
{
Field f = fields[i].getField();
throw new ClassCastException(
"cannot assign instance of " +
val.getClass().getName() + " to field " +
f.getDeclaringClass().getName() + "." +
f.getName() + " of type " +
f.getType().getName() + " in instance of " +
obj.getClass().getName());
}
if (!dryRun)
unsafe.putReference(obj, key, val);
}
default -> throw new InternalError();
}
}
}
In my scenario,
obj is an instance of a.b.c.SubClass
vals has 26 elements of which index 17 is a CollSer
dryRun is true
The “i” value is 20.
typecode[i] is ‘L’
numPrimFields is 3
offset[i] is 17
types[i - numPrimFields] is java.util.List
val is a CollSer (array null, tag 1 (IMM_LIST))
The line:
!types[i - numPrimFields].isInstance(val)
Fails because java.util.List is not an instance of java.util.CollSer I think (not sure) CollSer should probably have already been replaced by a List by CollSer’s readResolve() method.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No Exception
ACTUAL -
Caused by: java.lang.ClassCastException: cannot assign instance of java.util.CollSer to field a.b.c.BaseClass.aField of type java.util.List in instance of a.b.c.SubClass.
at java.base/java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2227)
at java.base/java.io.ObjectStreamClass$FieldReflector.checkObjectFieldValueTypes(ObjectStreamClass.java:2191)
at java.base/java.io.ObjectStreamClass.checkObjFieldValueTypes(ObjectStreamClass.java:1478)
at java.base/java.io.ObjectInputStream$FieldValues.defaultCheckFieldValues(ObjectInputStream.java:2657)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2471)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2242)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1742)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:514)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:472)
… 4200 other lines
CUSTOMER SUBMITTED WORKAROUND :
Note that I have used Unmodifiable Maps Lists ... all over this code without problems. It is just à this one usage point where using List.copyOf() method causes this exception at unserialisation time. Using the original modifiable List prevents the exception from being thrown.
FREQUENCY : rarely
- duplicates
-
JDK-8024931 Deserialization fails with cyclic object graph and serial proxy
-
- Open
-
- relates to
-
JDK-8331224 ClassCastException in ObjectInputStream hides ClassNotFoundException
-
- Closed
-
Cannot assign instance of java.util.CollSer to java.util.List
-
Bug
-
Resolution: Duplicate
-
P4
-
20
-
generic
-
generic
ADDITIONAL SYSTEM INFORMATION :
java version "20" 2023-03-21
Java(TM) SE Runtime Environment (build 20+36-2344)
Java HotSpot(TM) 64-Bit Server VM (build 20+36-2344, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
In a specific condition, I cannot unserialize an object that has references to a List created with List.copyOf().
I have this exception while unserializing an object:
java.lang.ClassCastException: cannot assign instance of java.util.CollSer to field a.b.c.BaseClass.aField of type java.util.List in instance of a.b.c.SubClass.
At serialization, the a.b.c.BaseClass.aField does contain a List that was created like this
return List.copyOf(originalList);
I have a “simple” workaround to fix the problem by changing the previous line to:
return originalList.
Note that the list may be shared by multiple instances of a.b.c.BaseClass.
see also:
https://stackoverflow.com/questions/75804762/classcastexception-when-unserializing-an-immutable-list-cannot-assign-instance
https://stackoverflow.com/questions/65613929/map-in-activemq-objectmessage-throws-classcastexception-cannot-assign-instance
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
I can reproduce this problem systematically. Unfortunately, this is a huge object being serialized (215 classes, 900MB on disk, error stack trace is 4200 lines). This object has been growing for years. It uses unmodifiable Maps, Lists, Sets ... all over without problems. It is just à this one usage point added recently where using List.copyOf() method causes this exception. I have tried to reproduce this problem using a small test case unsuccessfully.
Here is the code and state at the point of exception:
If I break and debug at the exception point (this is JDK 17 code) at java.base/java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2227)
private void setObjFieldValues(Object obj, Object[] vals, boolean dryRun) {
if (obj == null) {
throw new NullPointerException();
}
for (int i = numPrimFields; i < fields.length; i++) {
long key = writeKeys[i];
if (key == Unsafe.INVALID_FIELD_OFFSET) {
continue; // discard value
}
switch (typeCodes[i]) {
case 'L', '[' -> {
Object val = vals[offsets[i]];
if (val != null &&
!types[i - numPrimFields].isInstance(val))
{
Field f = fields[i].getField();
throw new ClassCastException(
"cannot assign instance of " +
val.getClass().getName() + " to field " +
f.getDeclaringClass().getName() + "." +
f.getName() + " of type " +
f.getType().getName() + " in instance of " +
obj.getClass().getName());
}
if (!dryRun)
unsafe.putReference(obj, key, val);
}
default -> throw new InternalError();
}
}
}
In my scenario,
obj is an instance of a.b.c.SubClass
vals has 26 elements of which index 17 is a CollSer
dryRun is true
The “i” value is 20.
typecode[i] is ‘L’
numPrimFields is 3
offset[i] is 17
types[i - numPrimFields] is java.util.List
val is a CollSer (array null, tag 1 (IMM_LIST))
The line:
!types[i - numPrimFields].isInstance(val)
Fails because java.util.List is not an instance of java.util.CollSer I think (not sure) CollSer should probably have already been replaced by a List by CollSer’s readResolve() method.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No Exception
ACTUAL -
Caused by: java.lang.ClassCastException: cannot assign instance of java.util.CollSer to field a.b.c.BaseClass.aField of type java.util.List in instance of a.b.c.SubClass.
at java.base/java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2227)
at java.base/java.io.ObjectStreamClass$FieldReflector.checkObjectFieldValueTypes(ObjectStreamClass.java:2191)
at java.base/java.io.ObjectStreamClass.checkObjFieldValueTypes(ObjectStreamClass.java:1478)
at java.base/java.io.ObjectInputStream$FieldValues.defaultCheckFieldValues(ObjectInputStream.java:2657)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2471)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2242)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1742)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:514)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:472)
… 4200 other lines
CUSTOMER SUBMITTED WORKAROUND :
Note that I have used Unmodifiable Maps Lists ... all over this code without problems. It is just à this one usage point where using List.copyOf() method causes this exception at unserialisation time. Using the original modifiable List prevents the exception from being thrown.
FREQUENCY : rarely
java version "20" 2023-03-21
Java(TM) SE Runtime Environment (build 20+36-2344)
Java HotSpot(TM) 64-Bit Server VM (build 20+36-2344, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
In a specific condition, I cannot unserialize an object that has references to a List created with List.copyOf().
I have this exception while unserializing an object:
java.lang.ClassCastException: cannot assign instance of java.util.CollSer to field a.b.c.BaseClass.aField of type java.util.List in instance of a.b.c.SubClass.
At serialization, the a.b.c.BaseClass.aField does contain a List that was created like this
return List.copyOf(originalList);
I have a “simple” workaround to fix the problem by changing the previous line to:
return originalList.
Note that the list may be shared by multiple instances of a.b.c.BaseClass.
see also:
https://stackoverflow.com/questions/75804762/classcastexception-when-unserializing-an-immutable-list-cannot-assign-instance
https://stackoverflow.com/questions/65613929/map-in-activemq-objectmessage-throws-classcastexception-cannot-assign-instance
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
I can reproduce this problem systematically. Unfortunately, this is a huge object being serialized (215 classes, 900MB on disk, error stack trace is 4200 lines). This object has been growing for years. It uses unmodifiable Maps, Lists, Sets ... all over without problems. It is just à this one usage point added recently where using List.copyOf() method causes this exception. I have tried to reproduce this problem using a small test case unsuccessfully.
Here is the code and state at the point of exception:
If I break and debug at the exception point (this is JDK 17 code) at java.base/java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2227)
private void setObjFieldValues(Object obj, Object[] vals, boolean dryRun) {
if (obj == null) {
throw new NullPointerException();
}
for (int i = numPrimFields; i < fields.length; i++) {
long key = writeKeys[i];
if (key == Unsafe.INVALID_FIELD_OFFSET) {
continue; // discard value
}
switch (typeCodes[i]) {
case 'L', '[' -> {
Object val = vals[offsets[i]];
if (val != null &&
!types[i - numPrimFields].isInstance(val))
{
Field f = fields[i].getField();
throw new ClassCastException(
"cannot assign instance of " +
val.getClass().getName() + " to field " +
f.getDeclaringClass().getName() + "." +
f.getName() + " of type " +
f.getType().getName() + " in instance of " +
obj.getClass().getName());
}
if (!dryRun)
unsafe.putReference(obj, key, val);
}
default -> throw new InternalError();
}
}
}
In my scenario,
obj is an instance of a.b.c.SubClass
vals has 26 elements of which index 17 is a CollSer
dryRun is true
The “i” value is 20.
typecode[i] is ‘L’
numPrimFields is 3
offset[i] is 17
types[i - numPrimFields] is java.util.List
val is a CollSer (array null, tag 1 (IMM_LIST))
The line:
!types[i - numPrimFields].isInstance(val)
Fails because java.util.List is not an instance of java.util.CollSer I think (not sure) CollSer should probably have already been replaced by a List by CollSer’s readResolve() method.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No Exception
ACTUAL -
Caused by: java.lang.ClassCastException: cannot assign instance of java.util.CollSer to field a.b.c.BaseClass.aField of type java.util.List in instance of a.b.c.SubClass.
at java.base/java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2227)
at java.base/java.io.ObjectStreamClass$FieldReflector.checkObjectFieldValueTypes(ObjectStreamClass.java:2191)
at java.base/java.io.ObjectStreamClass.checkObjFieldValueTypes(ObjectStreamClass.java:1478)
at java.base/java.io.ObjectInputStream$FieldValues.defaultCheckFieldValues(ObjectInputStream.java:2657)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2471)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2242)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1742)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:514)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:472)
… 4200 other lines
CUSTOMER SUBMITTED WORKAROUND :
Note that I have used Unmodifiable Maps Lists ... all over this code without problems. It is just à this one usage point where using List.copyOf() method causes this exception at unserialisation time. Using the original modifiable List prevents the exception from being thrown.
FREQUENCY : rarely
- duplicates
-
JDK-8024931 Deserialization fails with cyclic object graph and serial proxy
-
- Open
-
- relates to
-
JDK-8331224 ClassCastException in ObjectInputStream hides ClassNotFoundException
-
- Closed
-