Virtual threads created more platform threads
Chen Liang
liangchenblue at gmail.com
Wed Jul 2 04:57:56 UTC 2025
Hello Jianbin, please provide a test case that can reproduce this issue on
24. 21 is not supported by active JDK development.
On Tue, Jul 1, 2025, 23:52 Jianbin Chen <jianbin at apache.org> wrote:
> Hi everyone,
> thank you for your replies and assistance. So this issue occurring in JDK
> 21 is considered normal behavior, correct? However, I've observed that
> these expanded threads are not being garbage collected - they remain in a
> waiting state for several minutes without disappearing. Sometimes they can
> expand to several hundred threads, and these threads, once created, remain
> unused, continuously wasting thread resources. Therefore, I'm attaching a
> local reproduction example of this issue to ensure the information in this
> email is complete.
> -Djava.util.concurrent.ForkJoinPool.common.parallelism=1
> `
> The following example clearly shows the forkjoinpool expanding. I have
> also recorded the runtime stack trace for this and submitted it as an
> attachment.
>
> ```
> public static void main(String[] args) throws InterruptedException {
> Executor executor =
> ThreadPoolFactory.newVirtualThreadPerTaskExecutor();
> String a = "a";
> executor.execute(() -> {
> synchronized (a) {
> try {
> a.wait();
> } catch (InterruptedException e) {
> throw new RuntimeException(e);
> }
> }
> });
> executor.execute(() -> {
> synchronized (a) {
> try {
> a.wait();
> } catch (InterruptedException e) {
> throw new RuntimeException(e);
> }
> }
> });
> Thread.sleep(120000);
> }
> ```
> After switching to using condition, it can be clearly observed through
> jstack that the forkjoinpool did not expand as many threads, but 3 threads
> still appeared, which might be related to incorrect usage of my JVM
> parameters.
>
> ```
> public static void main(String[] args) throws InterruptedException {
> Executor executor =
> ThreadPoolFactory.newVirtualThreadPerTaskExecutor();
> List<ReentrantLock> list = new ArrayList<>();
> list.add(new ReentrantLock());
> list.add(new ReentrantLock());
> list.add(new ReentrantLock());
> list.add(new ReentrantLock());
> list.add(new ReentrantLock());
> list.add(new ReentrantLock());
> for (int i = 0; i < list.size(); i++) {
> ReentrantLock value = list.get(i);
> Condition condition = value.newCondition();
> executor.execute(() -> {
> value.lock();
> try {
> condition.await();
> } catch (InterruptedException e) {
> throw new RuntimeException(e);
> }finally {
> value.unlock();
> }
> });
> }
> Thread.sleep(120000);
> }
> ```
>
> Best Regards.
> Jianbin Chen, github-id: funky-eyes
>
> Peter Eastham <petereastham at gmail.com> 于 2025年7月2日周三 12:16写道:
>
>> I hope to not create noise with my own comments, and I will concur with
>> you that JEP 491 should mean this is resolved in Java 24, which Jianbin
>> Chen should try out before and then alongside Robert's recommendation for
>> creating a very simple reproduction.
>>
>> As Java 21 is still the current LTS, it isn't completely unreasonable to
>> forward concerns to the mailing list. My understanding in this particular
>> case is that JEP 491 is not going to be back ported to Java 21 as it has a
>> dependency from a change in Java 23. (Potentially more, I can't remember
>> the conversation completely, I only skimmed that email chain)
>>
>>
>> Thanks,
>> - Peter
>>
>> P.S. As I do a similar job, I'd like to call out that Vendors letting the
>> occasional support question slip into here is a fine price to pay for the
>> amount of questions they handle instead.
>>
>>
>>
>> On Tue, Jul 1, 2025, 9:17 PM Chen Liang <liangchenblue at gmail.com> wrote:
>>
>>> Hello, I don't think this would happen for JDK 24 - JEP 491 removed the
>>> code that calls Blocker in Object.wait, which is exactly the goal of that
>>> JEP.
>>>
>>> Note that virtual threads are still pinned when call stack goes into
>>> native, as native execution may pass address to stack variables that will
>>> be lost in context switches. In these cases, the traditional managed block
>>> happens again.
>>>
>>> P.S. I personally think it is somewhat not responsible for JDK vendors
>>> to ask users to upstream a question for an older JDK release that might no
>>> longer apply on the latest release to a development-oriented mailing list.
>>>
>>> On Tue, Jul 1, 2025 at 9:47 PM Jianbin Chen <jianbin at apache.org> wrote:
>>>
>>>>
>>>> Hi Loom-dev Community,
>>>>
>>>> I have a question about platform thread creation triggered by calling
>>>> future.get() within virtual threads, and I would like to ask the community
>>>> for assistance. The detailed information can be found in this issue:
>>>> https://github.com/adoptium/adoptium-support/issues/1319. I hope to
>>>> receive some help from the community regarding this matter. Thank you.
>>>> Additionally, I'd like to know if this situation will still occur in
>>>> JDK 24 and above?
>>>>
>>>> Best Regards.
>>>> Jianbin Chen, github-id: funky-eyes
>>>>
>>>>
>>>> Best Regards.
>>>> Jianbin Chen, github-id: funky-eyes
>>>>
>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20250701/4b7ea2d6/attachment-0001.htm>
More information about the loom-dev
mailing list