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

ZGC: ZWorker Threads Continue Marking After System.exit() called

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 17
    • 16, 17
    • hotspot
    • gc
    • b20
    • x86_64
    • os_x

      ADDITIONAL SYSTEM INFORMATION :
      openjdk version "16" 2021-03-16
      OpenJDK Runtime Environment (build 16+35-2229)
      OpenJDK 64-Bit Server VM (build 16+35-2229, mixed mode, sharing)

      Mac OS X Catalina

      A DESCRIPTION OF THE PROBLEM :
      On OS X, it appears that some ZWorker threads continue running even after System.exit() or kill or CTRL+C have been used to kill the process. With this experiment it can continue for up to a minute.

      In this experiment, we create thousands of linked lists in hundreds of threads. It is a nasty dataset, and probably not what would be encountered "in the wild". However, all the other GC algorithms shut down immediately, such as SerialGC, Throughput GC, CMS, G1, Shenandoah and even Epsilon.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Please run the attached code with the following JVM parameters:

      -Xmx50g -Xms50g -XX:+UseZGC

      After one minute, the timer thread calls System.exit(). The shutdown hook thread is immediately called and we would expect the JVM to shut down within about a second.

      We only managed to produce this bug on OS X, not on Linux.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Expected result would be for the JVM to shut down after about a minute. Once we see the output

      Shut down initiated - total time = 60004ms

      Then the JVM should shut down almost immediately.
      ACTUAL -
      The JVM continues running after the line

      Shut down initiated - total time = 60004ms

      The main thread still runs, as well as the threads that we started in the test. In the

      ---------- BEGIN SOURCE ----------
      import java.util.*;
      import java.util.concurrent.*;
      import java.util.concurrent.atomic.*;
      import java.util.stream.*;

      /**
       * Run with java -Xmx50g -Xms50g -XX:+UseZGC.
       * <p>
       * Once the Shut down is initiated, the JVM does not immediately
       * stop, but the ZWorker threads are still running doing marking.
       *
       * @author Heinz M. Kabutz
       */
      public class StrainingZGC {
        private static final LongAdder total = new LongAdder();
        private static final int SIZE = 20000;
        private static final int THREADS = 200;

        public static void main(String... args) throws InterruptedException {
          Timer timer = new Timer(true);
          timer.schedule(new TimerTask() {
            public void run() {
              System.exit(0);
            }
          }, 60_000);
          long start = System.nanoTime();
          Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.printf("Shut down initiated - total time = %dms%n",
                ((System.nanoTime() - start) / 1_000_000));
          }));


          for (int i = 0; i < THREADS; i++) {
            int from = i * (SIZE / THREADS);
            int to = Math.min(from + (SIZE / THREADS) * 10, SIZE);
            Thread thread = new Thread(() -> {
              List<List<Integer>> listOfLists = new ArrayList<>();
              for (int j = 0; j < SIZE / THREADS; j++) {
                listOfLists.add(
                    IntStream.range(0, SIZE)
                        .boxed()
                        .collect(Collectors.toCollection(LinkedList::new)));
              }

              while (true) {
                total.add(listOfLists.stream().mapToLong(
                    list -> list.stream().mapToLong(Integer::longValue).sum()
                ).sum());
                try {
                  Thread.sleep(2000);
                } catch (InterruptedException e) {
                  throw new CancellationException("interrupted");
                }
              }
            });
            thread.start();
          }

          while (true) {
            System.out.println("total = " + total);
            Thread.sleep(5000);
          }
        }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Don't create such a ridiculous object graph :)

      FREQUENCY : always


            pliden Per Liden (Inactive)
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              Resolved: