Index: java/lang/ThreadGroup.java =================================================================== RCS file: /cvsroot/classpath/classpath/java/lang/ThreadGroup.java,v retrieving revision 1.17 diff -u -r1.17 ThreadGroup.java --- java/lang/ThreadGroup.java 6 Dec 2004 20:43:13 -0000 1.17 +++ java/lang/ThreadGroup.java 10 Dec 2004 08:47:52 -0000 @@ -70,9 +70,12 @@ /** The group name, non-null. */ final String name; - /** The threads in the group. */ + /** The active threads in the group. */ private final Vector threads = new Vector(); + /** The number of inactive threads in the group */ + private int inactiveThreads; + /** Child thread groups, or null when this group is destroyed. */ private Vector groups = new Vector(); @@ -695,7 +698,8 @@ } /** - * Add a thread to the group. Called by Thread constructors. + * Add a thread to the group. Called by the VM for Threads + * started in native code, or by Thread.start() for Java threads. * * @param t the thread to add, non-null * @throws IllegalThreadStateException if the group is destroyed @@ -708,6 +712,24 @@ } /** + * Increment the count of inactive threads. Whenever a Thread + * object is created this count should be incremented so that + * we know that the group isn't empty. + */ + final synchronized void addInactiveThread() + { + inactiveThreads++; + } + + /** + * Decrement the count inactive threads. + */ + final synchronized void removeInactiveThread() + { + inactiveThreads--; + } + + /** * Called by the VM to remove a thread that has died. * * @param t the thread to remove, non-null @@ -720,7 +742,8 @@ threads.remove(t); t.group = null; // Daemon groups are automatically destroyed when all their threads die. - if (daemon_flag && groups.size() == 0 && threads.size() == 0) + if (daemon_flag && groups.size() == 0 + && threads.size() == 0 && inactiveThreads == 0) { // We inline destroy to avoid the access check. groups = null; @@ -738,7 +761,8 @@ { groups.remove(g); // Daemon groups are automatically destroyed when all their threads die. - if (daemon_flag && groups.size() == 0 && threads.size() == 0) + if (daemon_flag && groups.size() == 0 + && threads.size() == 0 && inactiveThreads == 0) { // We inline destroy to avoid the access check. groups = null; Index: java/lang/Thread.java =================================================================== RCS file: /cvsroot/classpath/classpath/java/lang/Thread.java,v retrieving revision 1.10 diff -u -r1.10 Thread.java --- java/lang/Thread.java 6 Dec 2004 20:43:13 -0000 1.10 +++ java/lang/Thread.java 10 Dec 2004 08:47:52 -0000 @@ -339,7 +339,7 @@ daemon = current.daemon; contextClassLoader = current.contextClassLoader; - group.addThread(this); + group.addInactiveThread(); InheritableThreadLocal.newChildThread(this); } @@ -824,6 +824,9 @@ throw new IllegalThreadStateException(); VMThread.create(this, stacksize); + + group.addThread(this); + group.removeInactiveThread(); } /** @@ -970,4 +973,14 @@ group.removeThread(this); vmThread = null; } + + /** + * If we die before ever having been actived, we need to remove + * ourself from the ThreadGroup inactive count. + */ + protected void finalize() throws Throwable + { + if (group != null) + group.removeInactiveThread(); + } }