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