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

The first getDefaultToolkit() hangs if invoked during the process's shutdown.

XMLWordPrintable

    • x86_64
    • windows_10

      ADDITIONAL SYSTEM INFORMATION :
      Windows10(64bit), version 1903.
      java 13.0.1 2019-10-15
      Java(TM) SE Runtime Environment (build 13.0.1+9)
      Java HotSpot(TM) 64-Bit Server VM (build 13.0.1+9, mixed mode, sharing)

      A DESCRIPTION OF THE PROBLEM :
       When java.awt.Toolkit.getToolkit() is invoked, it hangs if (0)this is the first call (directly/indirectl) of the method and (1)the shutdown of the java process has already begun. This bug affects various methods including SwingUtilities.invokeLater(Runnable). This is serious because this may easily and unexpectedly cause a java process to hang in such cases where the program has a shutdown hook that tries to, for example, interact with the system clipboard or get the size of the screen, (or just try to gain a synchronization lock in which another thread does the above-mentioned things.)

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Do as I have described above, or execute my sample code pasted below.
      I have no idea whether or not this bug can happen on Linux.

      ACTUAL -
      about my sample code:
      (A) If the code is executed without any args, as the first call of getToolkit() takes place after the shutting down, the call hangs and so does the entire java process.
      (A) If with some args, as the first getToolkit() is not after the start of shutting down, the process finishes fine. You can there use the obtained Toolkit for various purposes. Even you can alternatively execute SwingUtilities.invokeAndWait(Runnable) there.

      ---------- BEGIN SOURCE ----------
      import java.awt.*;

      public class ToolkitTest{

      public static void main(String... args) throws Exception{
      if(args.length > 0)Toolkit.getDefaultToolkit();

      Runtime.getRuntime().addShutdownHook(
      new Thread(ToolkitTest::shutdown)
      );
      new Thread(ToolkitTest::task).start();
      System.exit(0);
      }

      private static final Object lock = new Object();
      private static int a = 0;

      public static void shutdown(){
      synchronized(lock){
      if(a == 0){
      a = 1;
      }
      }

      //wait till the other thread allows me to exit.
      while(true){
      synchronized(lock){
      if(a == 2){
      break;
      }
      }
      }
      }

      public static void task(){
      //wait until the shutdown starts.
      while(true){
      synchronized(lock){
      if(a == 1){
      break;
      }
      }
      }

      try{
      System.out.println(
      Toolkit.getDefaultToolkit()
      );
      System.out.println("done. ");
      }catch(Exception e){
      System.out.println("exception: " + e);
      }

      //allow shutdown hook to exit.
      while(true){
      synchronized(lock){
      a = 2;
      break;
      }
      }
      }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      If I am programming a tool, I can call Toolkit.getToolkit() in the first line of the main method. If I am programming a library, insert the call of it before the places adding a potentially-risky shutdown hook (though it taints the code). If I were to fix the java api, well, it looks difficult...

      FREQUENCY : always


            pardesha Pardeep Sharma
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: