Another thing our colleague found seems to be a problem with circular
references and deserialization:

https://docs.oracle.com/en/java/javase/17/docs/specs/serialization/input.html#the-readresolve-method

However, during the serialization of an object with the writeReplace
method, all references to the original object in the replacement object's
object graph are replaced with references to the replacement object.
Therefore in cases where an object being serialized nominates a replacement
object whose object graph has a reference to the original object,
deserialization will result in an incorrect graph of objects. Furthermore,
if the reference types of the object being read (nominated by writeReplace)
and the original object are not compatible, the construction of the object
graph will raise a ClassCastException.

I personally didn't dig into the details... She introduced some object
checkers to help spot these things. If someone is interested I can ask my
manager if we can share this code with the community. As said I'm just
partially aware of the details... at the moment.


On Thu, May 1, 2025 at 9:47 AM Jonathan Locke <j...@thanlocke.com> wrote:

> I haven’t read the ticket carefully enough, but I’m wondering if you know:
> is the problem completely deterministic?
> If so, the tests should always catch it if there is a test that tests the
> serialization of each lambda (which is a lot of work for something that
> should just work in the first place!).
>
> Jon
>
> > On May 1, 2025, at 8:38 AM, Ernesto Reinaldo Barreiro <
> reier...@gmail.com> wrote:
> >
> > Hi,
> >
> > On Thu, May 1, 2025 at 9:22 AM Emond Papegaaij <
> emond.papega...@gmail.com <mailto:emond.papega...@gmail.com>>
> > wrote:
> >
> >> Hi,
> >>
> >> In our application we've also had these issues. As we do have quite a
> >> comprehensive test suite, I tried to detect these issues in tests, but I
> >> was unable to create a reliable way of detecting them. It seems that
> it's
> >> not always related to the actual lambda being serialized, but the entry
> >> point of the deserialization of that lambda. Many of the issues we could
> >> only reproduce after reloading a page several times. So we just gave up
> and
> >> make sure we do not use lambda's in some area's. Somehow, certain
> classes
> >> in our application are way more sensitive than others to these problems.
> >>
> >>
> > We are not 100% certain we are discovering all cases via our tests
> either.
> > But it helped so far. We started doing this half a year ago and a new
> > version of our product will be out soon... We will see how things go in
> > production and how effective what we do is.
> >
> >
> >
> >> Best regards,
> >> Emond
> >>
> >> Op do 1 mei 2025 om 15:54 schreef Ernesto Reinaldo Barreiro <
> >> reier...@gmail.com>:
> >>
> >>> Hi,
> >>>
> >>> We had also problems and one colleague of mine found out they are all
> >>> related to
> >>>
> >>> https://bugs.openjdk.org/browse/JDK-8024931
> >>>
> >>> We hunted down all of those. Additionally, we have a "special mode" to
> >> run
> >>> our application where we report all serialization problems into some
> >>> separated log file and we run our selenium tests against such instances
> >>> periodically. Thus, we have an early warning system telling us when we
> >>> reintroduce such problems.
> >>>
> >>> Another problem we found with the use of lambdas is that you have to be
> >>> very careful because you can easily serialize things you don't need to
> >>> serialize (even if they are serializable)
> >>>
> >>>
> >>> On Tue, Apr 29, 2025 at 1:06 AM Tobias Gierke <
> >>> tobias.gie...@code-sourcery.de> 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
> >>>>
> >>>> ||
> >>>>
> >>>
> >>>
> >>> --
> >>> Regards - Ernesto Reinaldo Barreiro
> >>>
> >>
> >
> >
> > --
> > Regards - Ernesto Reinaldo Barreiro
>
>

-- 
Regards - Ernesto Reinaldo Barreiro

Reply via email to