I’m not sure I fully understand that JDK ticket, but maybe implement a wrapper 
class that does custom serialization of a lambda argument? If it could be made 
to work at all, it would be fragile because you’d have to introspect on an 
internal implementation detail of the JDK (SerializedLambda), but the syntax 
wouldn’t be terrible. It would just involve wrapping each lambda in a method 
invocation. 

I asked Uncle Chat to write this up for me and the code looked straightforward 
enough, but no idea if that code actually works.

Hope the idea leads somewhere useful.

Jon

Sent from my iPhone

> On Apr 30, 2025, at 2:27 AM, Martijn Dashorst <[email protected]> 
> wrote:
> 
> In our experience dealing with this issue we noticed that using method
> references works well (enough), and if that fails falling back to
> anon-inner classes (or nested or...).
> 
> It sucks because it is difficult to reverse engineer which lambda is unable
> to be deserialized because of how deserialization works. IIRC I've updated
> the serialization/deserialization protocol of Wicket by adding a header for
> which page class is serialized/deserialized so that at least you know which
> page class it was that contains the lambda (am unable to find the code
> though)
> 
> Martijn
> 
> 
>> On Tue, Apr 29, 2025 at 8:06 AM Tobias Gierke <
>> [email protected]> 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
>> 
>> ||
>> 
> 
> 
> --
> Become a Wicket expert, learn from the best: http://wicketinaction.com


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to