RemiFer1 opened a new issue, #3645:
URL: https://github.com/apache/fory/issues/3645

   ### Search before asking
   - [x] I had searched in the issues and found no open issues matching.
   
   ### Version
   Fory 0.17.0 (Java)
   
   ### Component(s)
   Java
   
   ### Description
   
   We hit a deserialization failure on a deeply nested object graph where 
reference tracking ends up off by exactly **one slot** the first time a 
`java.util.Collections$SetFromMap` (built via `Collections.newSetFromMap(new 
ConcurrentHashMap<>())`) is encountered.
   
   Symptoms match #1832 ("SetFromMapSerializer didn't handle nested reference 
right"), which was reported and closed by #1833 in Sep 2024 — so this looks 
like either a regression in 0.17.0, or a slightly different call shape that PR 
#1833 didn't cover.
   
   ### Minimal reproduce step
   
   We did **not** isolate a minimal repro — the bug only surfaces deep inside a 
large object graph (~76,000 ref-tracked slots before the failure point). 
Instead we localized the cause empirically with paired writer/reader 
instrumentation (described below).
   
   Conditions that were present:
   - `withRefTracking(true)`
   - `requireClassRegistration(true)` (Fory auto-registers 
`Collections$SetFromMap` at id 179)
   - A `Collections.newSetFromMap(new ConcurrentHashMap<>())` instance reached 
as part of a nested `Externalizable.writeExternal` -> `stream.writeObject(set)` 
flow (i.e., not a top-level `Fory.serialize(set)` call).
   
   ### What did you expect to see?
   
   Successful round-trip. Writer and reader allocate the same ref-slot index 
for the `Collections$SetFromMap` and for every object in its subtree.
   
   ### What did you see instead?
   
   `ClassCastException` on the read side, surfaced via 
`ExceptionUtils.handleReadFailed` (a wrong-typed object returned from 
`stream.readObject()` deep inside `readExternal`).
   
   ### Diagnosis
   
   We instrumented the `ObjectOutput`/`ObjectInput` adapters used for 
`Externalizable` serialization to log `[slotId, className]` for every 
ref-tracked allocation, and ran a save+load cycle on the same data. Diffing the 
two logs:
   
   - The two streams agreed **perfectly** for the first ~74,343 allocations, 
ending at the slot for the `Collections$SetFromMap` instance.
   - Inside that Set's serialization (~1314 unlogged slots — non-Externalizable 
Collection element loop dispatched through Fory's built-in 
`SetFromMapSerializer`), the **reader allocated exactly one more slot than the 
writer**.
   - All subsequent slots were shifted by +1. Later back-references in the 
stream then resolved one slot off, returning a wrong-typed object.
   
   ### Workaround
   
   Forcing `Collections$SetFromMap` to use a user-registered 
`CollectionSerializer` (one that writes/reads elements via plain `ctx.writeRef` 
/ `ctx.readRef` and uses a `Collections.newSetFromMap(new 
ConcurrentHashMap<>())` factory on the read side) makes the round-trip succeed. 
So the issue is specific to the built-in `SetFromMapSerializer`'s `onMapWrite` 
/ `onMapRead` ref-tracking accounting.
   
   ### Notes for triage
   
   - #1832 / #1833 dealt with the same symptom shape; PR #1833 added an 
`onMapWrite` fix. Worth checking whether that fix is reachable from the path 
where the Set is encountered transitively via `stream.writeObject(...)` inside 
a parent `writeExternal` (vs. the test cases in #1833 which serialize the Set 
as a top-level argument).
   - Happy to provide additional log output or test against a patched build if 
useful — just don't have a small enough graph to share publicly.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to