Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions release-notes/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ No changes since 3.2
(fix by @pjfanning, w/ Claude code)
#6223: Avoid quadratic Object Id rebinding for Builder- and delegate-based values
(fix by @cowtowncoder, w/ Claude code)
#6225: `ArrayStoreException` when a Builder-based typed array resolves a forward
Object Id reference within the same array

3.2.2 (14-Aug-2026)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -562,16 +562,17 @@ void resolveForwardReference(int index, Object value) {
* @since 3.2
*/
void replaceResolvedItem(ArrayReferring forRef, Object oldItem, Object newItem) {
if (_array == null) {
return;
}
// Only the slot of `forRef` itself: if the same id was forward-referenced
// more than once, each reference gets a call of its own. Scanning all
// slots instead would make rebinding N references take O(N^2) time.
final int index = forRef._index;
final Object slot = _accumulator.get(index);
if (slot == forRef || slot == oldItem) {
_array[index] = newItem;
// Since 3.2.3, [databind#6225]: rebinding may happen before
// buildArray(), so update the accumulator even without an array.
if (_array != null) {
Comment thread
cowtowncoder marked this conversation as resolved.
_array[index] = newItem;
}
_accumulator.set(index, newItem);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,36 @@ public void forwardReferenceInTypedArrayWithBuilder() throws Exception
"forward ref must be rebound from Builder to built object in typed array");
}

// [databind#6225]: rebind a Builder before the typed array is materialized.
@Test
public void forwardReferenceResolvedWithinTypedArrayWithBuilder() throws Exception

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When adding to pre existing test class, we courage tests to contain some information about original GitHub issue.

{
EntityArray entity = MAPPER.readValue("""
{"id":0,"refs":[1,{"id":1}]}
""", EntityArray.class);

assertEquals(2, entity.refs.length);
assertEquals(1, entity.refs[0].id);
assertSame(entity.refs[1], entity.refs[0]);
}

// [databind#6225]: repeated forward references share the final built value.
@Test
public void multipleForwardReferencesResolvedWithinTypedArrayWithBuilder() throws Exception
{
EntityArray entity = MAPPER.readValue("""
{"id":0,"refs":[1,2,1,{"id":2},null,{"id":1}]}
""", EntityArray.class);

assertEquals(6, entity.refs.length);
assertEquals(1, entity.refs[0].id);
assertEquals(2, entity.refs[1].id);
assertSame(entity.refs[5], entity.refs[0]);
assertSame(entity.refs[3], entity.refs[1]);
assertSame(entity.refs[5], entity.refs[2]);
assertNull(entity.refs[4]);
}

// ---- Delegating-creator variant ([databind#1706] + collection forward
// refs): the bound id'd instance is a transient delegate (Mutable*) which
// is replaced via updateObjectId after createUsingDelegate. Forward refs
Expand Down