Kobra
Kobra

Reputation: 1350

Virtual Thead Names on Intellij Debugger

Issue with Virtual Threads in IntelliJ Debugger

When using virtual threads in IntelliJ, the thread name is not displayed correctly in the debugger, even when explicitly set. Instead, it shows a default name like pool-1-thread-1.

Example Code

final ThreadFactory factory = Thread.ofVirtual().name("named-thread-", 0).factory();
final ExecutorService executor = Executors.newThreadPerTaskExecutor(factory);

executor.execute(() -> Thread.currentThread().getName())

Expected Behavior

The thread name should be displayed as named-thread-0 in the console output and on Intellij Debugger.

Actual Behavior

The thread name is displayed correctly in the console output as named-thread-0, but in the IntelliJ debugger, it shows as pool-3-thread-1.

example_intellij_debugger

Note

If I change the code to use a normal thread instead of a virtual thread, the thread name appears correctly in the debugger.

Edit

With @Basil Bourque example, it stills have the same behaviour: On Console console image

On Debug debug enter image description here

Upvotes: 1

Views: 73

Answers (1)

Basil Bourque
Basil Bourque

Reputation: 339837

The name appears in the title under Threads & Variables in IntelliJ IDEA 2025.1 EAP.

I wrote an example app, using basically your code. I changed the name to "my-own-named-thread" plus the counter.

package work.basil.example.threading;

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

public class VirtualThreadName
{
    final String whatever = "blah";

    public static void main ( String[] args )
    {
        System.out.println ( "Demo start at " + Instant.now ( ) );
        System.out.println ( Runtime.version ( ) );

        final ThreadFactory factory = Thread.ofVirtual ( ).name ( "my-own-named-thread-" , 0 ).factory ( );
        try (
                final ExecutorService executor = Executors.newThreadPerTaskExecutor ( factory )
        )
        {
            executor.execute ( ( ) -> {
                System.out.println ( Thread.currentThread ( ).getName ( ) );
                Instant now = Instant.now ( );
                try { Thread.sleep ( Duration.ofMinutes ( 7 ) ); } catch ( InterruptedException e ) { throw new RuntimeException ( e ); }
            } );
            try { Thread.sleep ( Duration.ofMinutes ( 7 ) ); } catch ( InterruptedException e ) { throw new RuntimeException ( e ); }
        }

        System.out.println ( "Demo done at " + Instant.now ( ) );
    }
}

Execution:

  • I ran this on Java 23.0.1+13 on macOS 15.2 (Sequoia), Apple M1 Pro chip.
  • I paused the debugger on the Instant now = Instant.now ( ); line.

Here is a screenshot.

screenshot of IntelliJ debugger > Threads & Variables showing name of thread in title area

Be aware that calling Executor#execute (inherited by ExecutorService) may or may not run your task on a background thread (see Javadoc). To ensure that your task runs on a background thread, call ExecutorService#submit or similar method on that sub-interface rather than execute on its super-interface.

Upvotes: 1

Related Questions