[External] : Re: Virtual thread memory leak because TrackingRootContainer keeps threads

Matthew Swift matthew.swift at gmail.com
Thu Jul 25 13:49:21 UTC 2024


Thanks for the quick response Alan. A couple of comments:

> You can specify a ThreadFactory to newThreadPerTaskExecutor so you can
> set the thread name if you need it. Virtual threads are meant to be
> lightweight and numerous so don't get a name by default. For many cases,
> this is okay as the they have a thread ID which will identity them in
> thread dumps and elsewhere.

That may be so, but it's not very flexible, unless I'm missing something,
because it's not possible to derive the thread name from the task itself.
Said otherwise, a ThreadFactory lets you create very generic thread names
like "HTTP Connection #1" ahead of time, but doesn't let you derive a rich
name from the Runnable itself, like "HTTP Connection from 1.2.3.4 to
5.6.7.8 on port 8080". I tried cheating a bit by relying on the toString()
of the Runnable, but sadly this doesn't work because the executor wraps the
provided Runnable before calling the thread factory (see
ThreadPerTaskExecutor#start(java.lang.Runnable)).

> A virtual thread that is blocked reading from a Socket will continue
> when there are bytes to read, the peer closes the connection, some I/O
> exception, or the thread is interrupted. So it will be strongly reachable.

Ah, of course, silly me. And, following from that, the VT is strongly
reachable when running because it is directly referenced by the carrier
thread itself.

Thanks
Matt


On Thu, 25 Jul 2024 at 14:55, Alan Bateman <Alan.Bateman at oracle.com> wrote:

>
>
> On 25/07/2024 13:21, Matthew Swift wrote:
> > Hmm, I'm starting to think I may have fallen into the same trap here
> > as Michal.
> >
> > I've been using virtual threads similar to platform threads for
> > performing IO tasks asynchronously.
> >
> > Background: originally, I was using
> > Executors#newVirtualThreadPerTaskExecutor to run these tasks, which
> > was fine because the Executor tracks the virtual threads it creates in
> > order to support shutdown. However, from an observability point of
> > view I've found the executor to be a bit frustrating because it is
> > impossible to set the thread name before the thread is scheduled to
> > run[1].
> You can specify a ThreadFactory to newThreadPerTaskExecutor so you can
> set the thread name if you need it. Virtual threads are meant to be
> lightweight and numerous so don't get a name by default. For many cases,
> this is okay as the they have a thread ID which will identity them in
> thread dumps and elsewhere.
>
>
> > This means that under heavy load where the FJ pool is busy a thread
> > dump shows many unnamed threads, which are waiting to be scheduled for
> > the first time. Admittedly, this is only a minor annoyance because I'm
> > more interested in the threads that are clogging up the FJ pool than
> > the ones which are waiting to use it, even so it'd be nice to have an
> > overall picture of what's active and what's queued (note also thread
> > names are included in JFR events, which is super helpful).
>
> With the Loom EA builds [1] you can use `jcmd <pid>
> Thread.vthread_summary` to get a summary view of all thread grouping so
> you get thread counts, a summary of the scheduler, timers, and any
> socket I/O that it outstanding. We would like to bring this diagnostic
> command into the main line JDK at some point.
>
> >
> > To remedy this, I've switched away from using an Executor and now I
> > just use "Thread.ofVirtual().name(initialName).start(task)". However,
> > I don't think all of the tasks are strongly reachable - some are "fire
> > and forget" tasks (e.g. async resource cleanup), so I may be
> > inadvertently relying on the JVM's observability support to keep these
> > tasks alive until they complete, which seems a bit brittle. In fact,
> > now that I think of it, it may not even be limited to fire and forget
> > tasks. A VT that is reading messages from a Socket could be GC'd
> A virtual thread that is blocked reading from a Socket will continue
> when there are bytes to read, the peer closes the connection, some I/O
> exception, or the thread is interrupted. So it will be strongly reachable.
>
> -Alan
>
> [1] https://jdk.java.net/loom/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20240725/948a22da/attachment-0001.htm>


More information about the loom-dev mailing list