--- old/src/share/classes/java/util/logging/Logger.java Thu Jun 10 16:28:03 2010 +++ new/src/share/classes/java/util/logging/Logger.java Thu Jun 10 16:28:00 2010 @@ -1,5 +1,5 @@ /* - * 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 @@ -184,6 +184,9 @@ // references from children to parents. private volatile Logger parent; // our nearest parent. private ArrayList> 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 @@ -1388,6 +1391,14 @@ 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. @@ -1404,6 +1415,15 @@ // 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); } } @@ -1437,13 +1457,44 @@ // Recursively update the level on each of our kids. if (kids != null) { - for (int i = 0; i < kids.size(); i++) { - WeakReference ref = kids.get(i); + for (Iterator> iter = kids.iterator(); + iter.hasNext(); ) { + WeakReference 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> iter = kids.iterator(); + iter.hasNext(); ) { + WeakReference 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); + } + } } }