src/share/classes/java/util/logging/Logger.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -182,10 +182,13 @@
     private static Object treeLock = new Object();
     // We keep weak references from parents to children, but strong
     // references from children to parents.
     private volatile Logger parent;    // our nearest parent.
     private ArrayList<WeakReference<Logger>> kids;   // WeakReferences to loggers that have us as parent
+    // marker to know if this Logger has already been visited during the
+    // current WeakReference cleanup pass
+    private int kidsCleanupMarker;
     private volatile Level levelObject;
     private volatile int levelValue;  // current effective level value
 
     /**
      * GLOBAL_LOGGER_NAME is a name for the global logger.

@@ -1386,10 +1389,18 @@
                     WeakReference<Logger> ref =  iter.next();
                     Logger kid =  ref.get();
                     if (kid == this) {
                         iter.remove();
                         break;
+                    } else if (kid == null) {
+                        // Since we're already iterating the previous
+                        // parent's kid list, remove any stale weak
+                        // references to Logger objects that have been
+                        // GC'ed. Note this will only cleanup stale weak
+                        // refs that we encounter before we find ourself
+                        // on the kids list.
+                        iter.remove();
                     }
                 }
                 // We have now removed ourself from our parents' kids.
             }
 

@@ -1402,10 +1413,19 @@
 
             // As a result of the reparenting, the effective level
             // may have changed for us and our children.
             updateEffectiveLevel();
 
+            // Look for possible weak reference cleanup from the new
+            // parent Logger down. The updateEffectiveLevel() call above
+            // might have already done some or none of this work so
+            // this call is the only way to be absolutely sure we have
+            // have checked for stale weak refs in every Logger in the
+            // parent Logger's hierarchy. See deleteStaleWeakRefs()
+            // below for why this marker is needed.
+            parent.kidsCleanupMarker = (int) System.currentTimeMillis();
+            parent.deleteStaleWeakRefs(parent.kidsCleanupMarker);
         }
     }
 
     // Recalculate the effective level for this node and
     // recursively for our children.

@@ -1435,17 +1455,48 @@
 
         // System.err.println("effective level: \"" + getName() + "\" := " + level);
 
         // Recursively update the level on each of our kids.
         if (kids != null) {
-            for (int i = 0; i < kids.size(); i++) {
-                WeakReference<Logger> ref = kids.get(i);
+            for (Iterator<WeakReference<Logger>> iter = kids.iterator();
+                 iter.hasNext(); ) {
+                WeakReference<Logger> ref = iter.next();
                 Logger kid =  ref.get();
                 if (kid != null) {
                     kid.updateEffectiveLevel();
+                } else {
+                    // Since we're already iterating this kid list,
+                    // remove any stale weak references to Logger
+                    // objects that have been GC'ed. Note this will
+                    // only cleanup stale weak refs that we encounter
+                    // when we have to update the effective Level value.
+                    iter.remove();
                 }
             }
+        }
+    }
+
+
+    // Recursively delete stale WeakReferences on each of our kids.
+    // The marker parameter is used to know if a kid has been visited
+    // before. This marker logic is needed because the Logging API
+    // currently permits loops to be created in the Logger hierarchy.
+    private void deleteStaleWeakRefs(int marker) {
+        if (kids != null) {
+            for (Iterator<WeakReference<Logger>> iter = kids.iterator();
+                 iter.hasNext(); ) {
+                WeakReference<Logger> ref = iter.next();
+                Logger kid =  ref.get();
+                if (kid == null) {
+                    // Logger has been GC'ed so delete the stale weak ref
+                    iter.remove();
+                } else if (kid.kidsCleanupMarker != marker) {
+                    // visit the non-GC'ed Logger (and its kids, if any)
+                    kid.kidsCleanupMarker = marker;
+                    kid.deleteStaleWeakRefs(marker);
+                }
+            }
         }
     }
 
 
     // Private method to get the potentially inherited