Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8336061

Virtual threads cannot be GC'ed before they terminate

XMLWordPrintable

    • generic
    • generic

      A DESCRIPTION OF THE PROBLEM :
      According to JEP 444, " if a virtual thread is blocked on, e.g., BlockingQueue.take(), and no other thread can obtain a reference to either the virtual thread or the queue, then the thread can be garbage collected — which is fine, since the virtual thread can never be interrupted or unblocked."

      It does not work with default setting jdk.trackAllThreads=true, because virtual thread are stored in jdk.internal.vm.ThreadContainers.RootContainer.TrackingRootContainer#VTHREADS

      The problem was not exist by default before in https://bugs.openjdk.org/browse/JDK-8302185 jdk.trackAllThreads was enabled by default


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Start example code and take heap dump

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Virtual thread is eligible for garbage collection
      ACTUAL -
      Virtual thread is accessible from GC root:

      io.Demo$AAAConsumer 0x604610278 16 B
      val$task of java.lang.VirtualThread$VThreadContinuation$1 0x604616bd8 40 B
      target of java.lang.VirtualThread$VThreadContinuation 0x604616b38 120 B
      cont of java.lang.VirtualThread 0x604616668 280 B
      key of java.util.concurrent.ConcurrentHashMap$Node 0x604617200 32 B
      java.util.concurrent.ConcurrentHashMap$Node[16] 0x6046171b0 112 B
      table of java.util.concurrent.ConcurrentHashMap 0x604614828 176 B
      map of java.util.concurrent.ConcurrentHashMap$KeySetView 0x604614810 200 B
      VTHREADS of jdk.internal.vm.ThreadContainers$RootContainer$TrackingRootContainer, GC Root: Sticky class 0x604614770 312 B


      ---------- BEGIN SOURCE ----------
      package io;

      import java.util.concurrent.ArrayBlockingQueue;
      import java.util.concurrent.TimeUnit;

      public class Demo {

          public static void main(String[] args) throws InterruptedException {
              Thread.ofVirtual().start(new AAAConsumer());
              // here I catch thread/heap dump
              TimeUnit.SECONDS.sleep(15);
          }

          static class AAAConsumer implements Runnable {

              @Override
              public void run() {
                  try {
                      new ArrayBlockingQueue<>(100).take();
                  } catch (InterruptedException e) {
                      System.out.println("AAAConsumer interrupted");
                  }
              }
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      -Djdk.trackAllThreads=false

      FREQUENCY : always


            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: