Hi,

we have had the same issue which is caused when you have code like the following in the same class!

The message in the crash was similar to "cannot assign instance of java.lang.invoke.SerializedLambda to field org.apache.wicket.AttributeModifier.replaceModel of type org.apache.wicket.model.IModel in instance of org.apache.wicket.behavior.AttributeAppender"

The problematic code:

Label label;

|add(new AttributeAppender("aria-describedby", label::getMarkupId, " "));|

|WebMarkupContainer container;|

|add(new AttributeAppender("aria-describedby", container::getMarkupId, " "));|

|I am pretty certain this is this bug https://bugs.openjdk.org/browse/JDK-8208752 and after rewriting the code to explicit inner classes this has never occured again.|

|In the meantime however we have migrated to inmemory Pagestore for performance reasons, so Serialisation is not a problem for us anymore.
|

|Greetings, |

|Johannes
|

On 29/04/2025 08:06, Tobias Gierke wrote:
Hi,

Our company is a long time Wicket user on a large code base (10+ years, >600k loc) and ever since lambdas got introduced in JDK 8, our Wicket applications have occasionally been plagued by random crashes during Wicket Page deserialization like this:

|Caused by: java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:109) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at com.vodecc.voipmng.boundary.wicket.WicketApplication$5.lambda$get$0(WicketApplication.java:864) ... 63 more Caused by: java.lang.ClassCastException: cannot assign instance of java.lang.invoke.SerializedLambda to field <someClass>.<someFieldWithTypeIModel> of type org.apache.wicket.model.IModel at java.base/java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2096) at java.base/java.io.ObjectStreamClass$FieldReflector.checkObjectFieldValueTypes(ObjectStreamClass.java:2060) at java.base/java.io.ObjectStreamClass.checkObjFieldValueTypes(ObjectStreamClass.java:1349) at java.base/java.io.ObjectInputStream$FieldValues.defaultCheckFieldValues(ObjectInputStream.java:2697) at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2498) at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2284) at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1762) at java.base/java.io.ObjectInputStream$FieldValues.&lt;init&gt;(ObjectInputStream.java:2618) at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2469) at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2284) at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1762) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:540) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:498) at java.base/java.util.ArrayList.readObject(ArrayList.java:981) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) |

The offending member field in this particular crash has a type of 'IModel<String>'.

With "random crashes" I mean that the same code sometimes works and sometimes crashes, seemingly dependent on the order in which (capturing?) lambdas are created or called.

I did spent some time looking into this and found quite a few *unresolved* JDK bugs related to ClassCastExceptions during lambda serialization:

https://bugs.openjdk.org/browse/JDK-8154236
https://bugs.openjdk.org/browse/JDK-8208752
https://bugs.openjdk.org/browse/JDK-8275387
https://bugs.openjdk.org/browse/JDK-8174864
https://bugs.openjdk.org/browse/JDK-8174865

A comment on JDK-8275387 seemed especially enlightening: "The root cause is always the same: java.lang.invoke.SerializedLambda can not hold enough information to correctly identify the which lambda should be (de-)serialized". This all points to https://bugs.openjdk.org/browse/JDK-8174864 as the root of the problem. That ticket mentions that currently, lambda serialization is a lossy transformation since only the first invocation of any unique "serialization key" will work (which would explain the randomness we observed).

We currently "fix" our crashes by using anonymous classes instead of lambda expressions but obviously this is not ideal - especially since (given enough indirections) it's quite hard to find out where the lambda causing the deserialization crash originated from.

Cheers,
Tobias

||

Reply via email to