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

JVM sometimes exits before all non-daemon threads quit

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P3 P3
    • None
    • 6u7, 6u10
    • core-libs
    • Cause Known
    • x86
    • windows_xp

      FULL PRODUCT VERSION :
      java version "1.6.0_10-rc2"
      Java(TM) SE Runtime Environment (build 1.6.0_10-rc2-b32)
      Java HotSpot(TM) Client VM (build 11.0-b15, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows XP [Version 5.1.2600]

      A DESCRIPTION OF THE PROBLEM :
      I reported this a few days ago, but I didn't realize how serious this was, and I have a much better example for reproducing it now.

      Setting the JVM's SecurityManager may cause the JVM to quit before all non-daemon threads have quit. I'm unsure of exactly what the parameters are that cause this, but for a given SecurityManager, it will seemingly always happen, or never happen.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run test case below.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Should print out some data from the SecurityManager, then slowly print the numbers 1-1000.
      ACTUAL -
      Prints out data from the SecurityManager, then prints "0" (sometimes), and quits.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package org.thedreaming.test;

      import java.io.FileDescriptor;
      import java.net.InetAddress;
      import java.security.Permission;


      public class SecurityManagerTest {

        public static void main(String[] args) {
          
          final SecurityManager securityManager = new SecurityManager() {
            @Override
            public void checkMemberAccess(Class<?> clazz, int which) {
              System.out.println("" + Thread.currentThread() + ": Checking access for " + clazz + " for " + which);
            }
            
            @Override
            public void checkPackageAccess(String pkg){
              System.out.println("" + Thread.currentThread() + ": Checking access for package " + pkg);
            }

            @Override
            public void checkAccept(String host, int port) {
              System.out.println("" + Thread.currentThread() + ": Accept");
            }

            @Override
            public void checkAccess(Thread t) {
              System.out.println("" + Thread.currentThread() + ": Access " + t);
            }

            @Override
            public void checkAccess(ThreadGroup g) {
              System.out.println("" + Thread.currentThread() + ": Access " + g);
            }

            @Override
            public void checkAwtEventQueueAccess() {
              System.out.println("" + Thread.currentThread() + ": AWT");
            }

            @Override
            public void checkConnect(String host, int port, Object context) {
              System.out.println("" + Thread.currentThread() + ": Connect for context");
            }

            @Override
            public void checkConnect(String host, int port) {
              System.out.println("" + Thread.currentThread() + ": Connect");
            }

            @Override
            public void checkCreateClassLoader() {
              System.out.println("" + Thread.currentThread() + ": Create class loader");
            }

            @Override
            public void checkDelete(String file) {
              System.out.println("" + Thread.currentThread() + ": Checking delete");
            }

            @Override
            public void checkExec(String cmd) {
              System.out.println("" + Thread.currentThread() + ": Checking exec");
            }

            @Override
            public void checkExit(int status) {
              super.checkExit(status);
            }

            @Override
            public void checkLink(String lib) {
              System.out.println("" + Thread.currentThread() + ": Checking link");
            }

            @Override
            public void checkListen(int port) {
              System.out.println("" + Thread.currentThread() + ": Checking listen");
            }

            @Override
            public void checkMulticast(InetAddress maddr) {
              System.out.println("" + Thread.currentThread() + ": Checking multicast");
            }

            @Override
            public void checkPackageDefinition(String pkg) {
              System.out.println("" + Thread.currentThread() + ": Checking pkg def");
            }

            @Override
            public void checkPermission(Permission perm, Object context) {
              System.out.println("" + Thread.currentThread() + ": Checking permission " + perm + " for context");
            }

            @Override
            public void checkPermission(Permission perm) {
              System.out.println("" + Thread.currentThread() + ": Checking permission " + perm);
            }

            @Override
            public void checkPrintJobAccess() {
              System.out.println("" + Thread.currentThread() + ": Checking print job");
            }

            @Override
            public void checkPropertiesAccess() {
              System.out.println("" + Thread.currentThread() + ": Checking property access");
            }

            @Override
            public void checkPropertyAccess(String key) {
              System.out.println("" + Thread.currentThread() + ": Checking property access: " + key);
            }

            @Override
            public void checkRead(FileDescriptor fd) {
              System.out.println("" + Thread.currentThread() + ": Checking read fd " + fd);
            }

            @Override
            public void checkRead(String file, Object context) {
              System.out.println("" + Thread.currentThread() + ": Checking read for context");
            }

            @Override
            public void checkRead(String file) {
              System.out.println("" + Thread.currentThread() + ": Checking read " + file);
            }

            @Override
            public void checkSecurityAccess(String target) {
              System.out.println("" + Thread.currentThread() + ": Checking security access");
            }

            @Override
            public void checkSetFactory() {
              System.out.println("" + Thread.currentThread() + ": Checking set factory");
            }

            @Override
            public void checkSystemClipboardAccess() {
              System.out.println("" + Thread.currentThread() + ": Checking clipboard access");
            }

            @Override
            public boolean checkTopLevelWindow(Object window) {
              System.out.println("" + Thread.currentThread() + ": Checking top level window");
              return super.checkTopLevelWindow(window);
            }

            @Override
            public void checkWrite(FileDescriptor fd) {
              System.out.println("" + Thread.currentThread() + ": Checking write fd " + fd);
            }

            @Override
            public void checkWrite(String file) {
              System.out.println("" + Thread.currentThread() + ": Checking write " + file);
            }
          };
          Thread t = new Thread() {
            public void run() {
              System.setSecurityManager(securityManager);
              
            }
          };
          t.start();
          try {
            t.join();
          } catch (Exception e) {
            e.printStackTrace();
          }
          
          Runnable runnable = new Runnable() {
            public void run() {
              for(int i = 0; i < 1000; i++) {
                System.out.println("" + i);
                try {
                  Thread.sleep(1000);
                } catch (InterruptedException e) {
                  System.out.println("Interrupted");
                }
              }
              System.out.println("Hello World");
              System.out.flush();
            }
          };
          
          Thread thread = new Thread(runnable);
          thread.start();
          System.out.println("Started " + thread.getName() + " " + thread.isDaemon() + " " + thread.isAlive());
        }
        
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      If you can keep track of all the threads you spawn, then "thread.join()" in the main thread for each child thread seems to fix this, but this is not an option in my case.

            chegar Chris Hegarty
            ryeung Roger Yeung (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Imported:
              Indexed: