Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ObjectMapper cannot work with a non-ThreadLocal based BufferRecycler pool #4321

Closed
1 task done
mariofusco opened this issue Jan 15, 2024 · 8 comments
Closed
1 task done
Labels
to-evaluate Issue that has been received but not yet evaluated

Comments

@mariofusco
Copy link
Contributor

Search before asking

  • I searched in the issues and found nothing similar.

Describe the bug

I was trying to integrate a new virtual threads friendly into Vert.x/Quarkus and found that jackson-databing cannot work with it, see quarkusio/quarkus#38196 (comment)

Version Information

2.16.1

Reproduction

I will provide an isolated reproducer asap, but this can be easily reproduced using any of the tests in the jackson quarkus extension after trying to to plug a custom pool.

Expected behavior

No response

Additional context

No response

@cowtowncoder
Copy link
Member

This was my big miss: basic due diligency would have been to add one happy-path test for jackson-databind, at minimum.
Thank you for reporting this @mariofusco . I'll see if I have time today to do basic reproduction at least.

@cowtowncoder
Copy link
Member

cowtowncoder commented Jan 15, 2024

Ok, well, adding basic verification (see com.fasterxml.jackson.databind.util.BufferRecyclersDatabindTest) did not reproduce the issue as far as I can see so I may need help with reproduction here.

But it does look like use of BufferRecycler by generator (via SegmentedStringWriter and ByteArrayBuilder) is at least sub-optimal, if not wrong.

@mariofusco
Copy link
Contributor Author

@cowtowncoder I will try to provide an isolated reproducer based on the Quarkus test case that I was investigating yesterday.

@mariofusco
Copy link
Contributor Author

I have understood why it is not possible to reproduce the problem with the jackson-core standard pools. Having configured one of them a single write operation acquires 2 different instances of BufferRecycler, see

image

which in my opinion is equally wrong. The pool implementation that we're trying to use in Vert.x/Quarkus is a bit smarter, recognizing the kind of thread that is requiring the resource and falling back to the ThreadLocal based implementation in case of a native thread. In this case the 2 subsequent acquires performed by the write operation retrive the same instance of BufferRecycler and try to register it twice as taken from a pool, thus triggering that exception. I added a simplified version of that hybrid pool to your test and reproduced the problem.

I'm not sure if that hybrid pool strategy should be considered an antipattern at this point or we should try to support it anyway, but in my opinion is not correct (or at least suboptimal) that a single write operation requires the use of 2 different BufferRecycler, so I will try to send a pull request fixing this.

@mariofusco
Copy link
Contributor Author

This change actually fixes our hybrid pool eclipse-vertx/vert.x@766f232

I believe this is a good improvement so I will leave it there. That said I believe there is still something wrong in jackson-databind for requiring more than one BufferRecycler for a single write operation. Please advice if this is something that you think it should (and could) be fixed, or you're happy with this for now.

@mariofusco
Copy link
Contributor Author

I sent a pull request to jackson-core with a tentative fix and also another one to jackson-databind demonstrating the problem.

As you can see with this change in place the same instance of BufferRecycler is used by both SegmentedStringWriter and IOContext.

image

@cowtowncoder
Copy link
Member

Yes, I did notice that separate BufferRecycler was requested from 2 places in ObjectMapper, for output buffer reuse (when serializing "as bytes" or "as string"). Ideally would not use different BufferRecycler -- I'll have a look at PRs you mention.

@cowtowncoder
Copy link
Member

As far as I understand, this is not longer concern; closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
to-evaluate Issue that has been received but not yet evaluated
Projects
None yet
Development

No branches or pull requests

2 participants