[
https://issues.apache.org/jira/browse/CAMEL-20199?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18100317#comment-18100317
]
Guillaume Nodet commented on CAMEL-20199:
-----------------------------------------
_Claude Code on behalf of [~gnodet]_
h3. Status Analysis (as of July 2026)
After auditing the codebase, here is the current status of the four sub-tasks
defined in this issue. The foundational infrastructure is fully in place — what
remains is a tail of mechanical component-level conversions.
h4. Sub-task 1: Replace synchronized with ReentrantLock — Largely Complete
The massive alphabetical sweep across all components (PRs #14972 - #16848 by
[~essobedo]) plus additional core work (PR #21703 by [~gnodet]) converted the
vast majority of synchronized blocks.
*Remaining (~108 usages in ~48 files, production code only):*
||Category||Count||Convertible?||
|{{MllpSocketBuffer.java}} (single file)|29|Yes — prime candidate, 27% of all
remaining|
|DOM/XML API safety ({{importNode}}, XPath)|~6|No — DOM spec requires it|
|CXF Continuation API|~4|No — third-party API contract|
|Dev/debug-only (DevSpanExporter, JFR console)|~10|Low priority — not on hot
paths|
|Core engine (transacted exchanges, debugger)|~8|Mostly intentional|
|*Straightforward conversion candidates*|*~20-25*|Yes — {{GuardedTaskStore}},
{{A2AProgress}}, {{JwksCache}}, {{KeycloakPublicKeyResolver}},
{{MiloClientCachingConnectionManager}}, etc.|
Core is effectively clean. ~20-25 component-level usages could still be
converted.
h4. Sub-task 2: Eliminate Problematic ThreadLocal Usage — Mostly Complete
The *ContextValue abstraction* is in place (PR #20702): JDK 17-24 uses
ThreadLocal, JDK 25+ uses ScopedValue. 5 core usages already migrated.
*Remaining raw ThreadLocal (10 usages):*
||Risk||File||What it caches||
|HIGH|{{camel-reactive-executor-tomcat}} {{TomcatReactiveExecutor}}|Worker
objects with ArrayDeque — on hot path, uses reflection on
{{Thread.threadLocals}} (breaks with VTs). Core equivalent already migrated but
this wasn't.|
|MODERATE|{{camel-snakeyaml}} {{SnakeYAMLDataFormat}}|Yaml parser instance —
moderately heavy, created per VT and never reused. WeakReference partially
mitigates.|
|LOW|{{AbstractCamelContext.componentsInCreation}}|HashSet — startup only|
|LOW|{{InternalRouteStartupManager.setupRoute}}|Route ref — startup only,
cleared after|
|LOW|{{camel-xpath}}, {{camel-datasonnet}}, {{camel-jq}}, {{camel-as2}},
{{camel-univocity}}|Exchange refs or small arrays — lightweight, properly
scoped|
h4. Sub-task 3: Use Semaphores for Concurrency Limiting — Complete
* {{BoundedExecutorService}} — semaphore-based ExecutorService wrapper,
automatically applied by {{DefaultThreadPoolFactory}} when virtual threads +
bounded queue
* SEDA {{virtualThreadPerTask}} — semaphore-gated concurrency with
{{concurrentConsumers}} as cap
* Throttler EIP — already semaphore-based ({{ConcurrentRequestsThrottler}})
* Rejected execution policies (CallerRuns, Abort, Discard) all supported
h4. Sub-task 4: JMX Exposure of ThreadPerTaskExecutor — Complete
PR #21701 added {{ManagedVirtualThreadExecutorMBean}},
{{ManagedVirtualThreadExecutor}}, lifecycle hooks in {{LifecycleStrategy}} for
non-{{ThreadPoolExecutor}} executors, full integration in
{{JmxManagementLifecycleStrategy}}, and tests.
h4. Bonus: Configuration & Documentation — Complete
* {{camel.main.virtualThreadsEnabled=true}} property (PR #21743)
* Comprehensive {{virtual-threads.adoc}} (1185 lines) covering enablement, SEDA
models, backpressure, ContextValue, best practices, examples
h3. Remaining Work (keeping open as umbrella)
||Priority||Item||Effort||
|High|Migrate {{TomcatReactiveExecutor}} to ContextValue (parity with
{{DefaultReactiveExecutor}})|Small|
|Medium|Convert {{MllpSocketBuffer}} (29 synchronized methods) to
ReentrantLock|Medium|
|Medium|Convert ~20-25 remaining component synchronized blocks|Medium|
|Medium|Migrate {{camel-snakeyaml}} Yaml caching away from ThreadLocal|Small|
|Low|Migrate context-passing ThreadLocals (xpath, datasonnet, jq, as2) to
ContextValue|Small each|
Overall the issue is ~85-90% complete. Keeping open as an umbrella for the
remaining component-level cleanup.
> Complete support of Virtual Threads
> -----------------------------------
>
> Key: CAMEL-20199
> URL: https://issues.apache.org/jira/browse/CAMEL-20199
> Project: Camel
> Issue Type: Improvement
> Components: came-core
> Reporter: Nicolas Filotto
> Assignee: Guillaume Nodet
> Priority: Major
> Fix For: 4.x
>
>
> For full support of Virtual Threads, several sub-tasks need to be done:
> * Avoid Lengthy and Frequent Pinning by replacing synchronized blocks with
> ReentrantLocks (use the option {{-Djdk.tracePinnedThreads=full}} to print
> stack traces when a thread blocks while pinned)
> * Don't Cache Expensive Reusable Objects in Thread-Local Variables by
> avoiding thread locals when possible since when using Virtual Threads, the
> objects will never be reused so if the thread-local variables are never
> reset, it will end up with an OOME.
> * Use Semaphores to Limit Concurrency instead of relying on the size of the
> thread pool when applicable
> * Allow to expose {{ThreadPerTaskExecutor}} through JMX indeed so far it is
> limited to {{ThreadPoolExecutor}}
> References
> [https://docs.oracle.com/en/java/javase/21/core/virtual-threads.html]
--
This message was sent by Atlassian Jira
(v8.20.10#820010)