< prev index next >

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

Print this page




  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 
  27 package java.util.logging;
  28 
  29 import java.io.*;
  30 import java.util.*;
  31 import java.security.*;
  32 import java.lang.ref.ReferenceQueue;
  33 import java.lang.ref.WeakReference;

  34 import sun.misc.JavaAWTAccess;
  35 import sun.misc.SharedSecrets;
  36 
  37 /**
  38  * There is a single global LogManager object that is used to
  39  * maintain a set of shared state about Loggers and log services.
  40  * <p>
  41  * This LogManager object:
  42  * <ul>
  43  * <li> Manages a hierarchical namespace of Logger objects.  All
  44  *      named Loggers are stored in this namespace.
  45  * <li> Manages a set of logging control properties.  These are
  46  *      simple key-value pairs that can be used by Handlers and
  47  *      other logging objects to configure themselves.
  48  * </ul>
  49  * <p>
  50  * The global LogManager object can be retrieved using LogManager.getLogManager().
  51  * The LogManager object is created during class initialization and
  52  * cannot subsequently be changed.
  53  * <p>


  83  * <p>
  84  * The properties for loggers and Handlers will have names starting
  85  * with the dot-separated name for the handler or logger.
  86  * <p>
  87  * The global logging properties may include:
  88  * <ul>
  89  * <li>A property "handlers".  This defines a whitespace or comma separated
  90  * list of class names for handler classes to load and register as
  91  * handlers on the root Logger (the Logger named "").  Each class
  92  * name must be for a Handler class which has a default constructor.
  93  * Note that these Handlers may be created lazily, when they are
  94  * first used.
  95  *
  96  * <li>A property "&lt;logger&gt;.handlers". This defines a whitespace or
  97  * comma separated list of class names for handlers classes to
  98  * load and register as handlers to the specified logger. Each class
  99  * name must be for a Handler class which has a default constructor.
 100  * Note that these Handlers may be created lazily, when they are
 101  * first used.
 102  *













 103  * <li>A property "&lt;logger&gt;.useParentHandlers". This defines a boolean
 104  * value. By default every logger calls its parent in addition to
 105  * handling the logging message itself, this often result in messages
 106  * being handled by the root logger as well. When setting this property
 107  * to false a Handler needs to be configured for this logger otherwise
 108  * no logging messages are delivered.
 109  *
 110  * <li>A property "config".  This property is intended to allow
 111  * arbitrary configuration code to be run.  The property defines a
 112  * whitespace or comma separated list of class names.  A new instance will be
 113  * created for each named class.  The default constructor of each class
 114  * may execute arbitrary code to update the logging configuration, such as
 115  * setting logger levels, adding handlers, adding filters, etc.
 116  * </ul>
 117  * <p>
 118  * Note that all classes loaded during LogManager configuration are
 119  * first searched on the system class path before any user class path.
 120  * That includes the LogManager class, any config classes, and any
 121  * handler classes.
 122  * <p>


 152     private volatile Properties props = new Properties();
 153     private final static Level defaultLevel = Level.INFO;
 154 
 155     // LoggerContext for system loggers and user loggers
 156     private final LoggerContext systemContext = new SystemLoggerContext();
 157     private final LoggerContext userContext = new LoggerContext();
 158     // non final field - make it volatile to make sure that other threads
 159     // will see the new value once ensureLogManagerInitialized() has finished
 160     // executing.
 161     private volatile Logger rootLogger;
 162     // Have we done the primordial reading of the configuration file?
 163     // (Must be done after a suitable amount of java.lang.System
 164     // initialization has been done)
 165     private volatile boolean readPrimordialConfiguration;
 166     // Have we initialized global (root) handlers yet?
 167     // This gets set to false in readConfiguration
 168     private boolean initializedGlobalHandlers = true;
 169     // True if JVM death is imminent and the exit hook has been called.
 170     private boolean deathImminent;
 171 



























 172     private final Map<Object, Runnable> listeners =
 173             Collections.synchronizedMap(new IdentityHashMap<>());
 174 
 175     static {
 176         manager = AccessController.doPrivileged(new PrivilegedAction<LogManager>() {
 177             @Override
 178             public LogManager run() {
 179                 LogManager mgr = null;
 180                 String cname = null;
 181                 try {
 182                     cname = System.getProperty("java.util.logging.manager");
 183                     if (cname != null) {
 184                         try {
 185                             Class<?> clz = ClassLoader.getSystemClassLoader()
 186                                     .loadClass(cname);
 187                             mgr = (LogManager) clz.newInstance();
 188                         } catch (ClassNotFoundException ex) {
 189                             Class<?> clz = Thread.currentThread()
 190                                     .getContextClassLoader().loadClass(cname);
 191                             mgr = (LogManager) clz.newInstance();
 192                         }
 193                     }
 194                 } catch (Exception ex) {
 195                     System.err.println("Could not load Logmanager \"" + cname + "\"");
 196                     ex.printStackTrace();
 197                 }
 198                 if (mgr == null) {
 199                     mgr = new LogManager();
 200                 }
 201                 return mgr;
 202 
 203             }
 204         });
 205     }
 206 
 207 
 208     // This private class is used as a shutdown hook.
 209     // It does a "reset" to close all open handlers.
 210     private class Cleaner extends Thread {
 211 
 212         private Cleaner() {
 213             /* Set context class loader to null in order to avoid
 214              * keeping a strong reference to an application classloader.
 215              */
 216             this.setContextClassLoader(null);
 217         }
 218 
 219         @Override
 220         public void run() {
 221             // This is to ensure the LogManager.<clinit> is completed
 222             // before synchronized block. Otherwise deadlocks are possible.
 223             LogManager mgr = manager;
 224 
 225             // If the global handlers haven't been initialized yet, we
 226             // don't want to initialize them just so we can close them!
 227             synchronized (LogManager.this) {


 858                         // we'll just loop around and try again.
 859                         result = findLogger(name);
 860                     }
 861                 } while (result == null);
 862             }
 863             return result;
 864         }
 865     }
 866 
 867     // Add new per logger handlers.
 868     // We need to raise privilege here. All our decisions will
 869     // be made based on the logging configuration, which can
 870     // only be modified by trusted code.
 871     private void loadLoggerHandlers(final Logger logger, final String name,
 872                                     final String handlersPropertyName)
 873     {
 874         AccessController.doPrivileged(new PrivilegedAction<Object>() {
 875             @Override
 876             public Object run() {
 877                 String names[] = parseClassNames(handlersPropertyName);
 878                 for (String word : names) {





 879                     try {
 880                         Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(word);
 881                         Handler hdl = (Handler) clz.newInstance();
 882                         // Check if there is a property defining the
 883                         // this handler's level.
 884                         String levs = getProperty(word + ".level");
 885                         if (levs != null) {
 886                             Level l = Level.findLevel(levs);
 887                             if (l != null) {
 888                                 hdl.setLevel(l);
 889                             } else {
 890                                 // Probably a bad level. Drop through.
 891                                 System.err.println("Can't set level for " + word);
 892                             }
 893                         }
 894                         // Add this Handler to the logger
 895                         logger.addHandler(hdl);




 896                     } catch (Exception ex) {
 897                         System.err.println("Can't load log handler \"" + word + "\"");
 898                         System.err.println("" + ex);
 899                         ex.printStackTrace();
 900                     }
 901                 }

 902                 return null;
 903             }
 904         });
 905     }
 906 
 907 
 908     // loggerRefQueue holds LoggerWeakRef objects for Logger objects
 909     // that have been GC'ed.
 910     private final ReferenceQueue<Logger> loggerRefQueue
 911         = new ReferenceQueue<>();
 912 
 913     // Package-level inner class.
 914     // Helper class for managing WeakReferences to Logger objects.
 915     //
 916     // LogManager.namedLoggers
 917     //     - has weak references to all named Loggers
 918     //     - namedLoggers keeps the LoggerWeakRef objects for the named
 919     //       Loggers around until we can deal with the book keeping for
 920     //       the named Logger that is being GC'ed.
 921     // LogManager.LogNode.loggerRef


1216         }
1217         try (final InputStream in = new FileInputStream(fname)) {
1218             final BufferedInputStream bin = new BufferedInputStream(in);
1219             readConfiguration(bin);
1220         }
1221     }
1222 
1223     /**
1224      * Reset the logging configuration.
1225      * <p>
1226      * For all named loggers, the reset operation removes and closes
1227      * all Handlers and (except for the root logger) sets the level
1228      * to null.  The root logger's level is set to Level.INFO.
1229      *
1230      * @exception  SecurityException  if a security manager exists and if
1231      *             the caller does not have LoggingPermission("control").
1232      */
1233 
1234     public void reset() throws SecurityException {
1235         checkPermission();

1236         synchronized (this) {
1237             props = new Properties();






1238             // Since we are doing a reset we no longer want to initialize
1239             // the global handlers, if they haven't been initialized yet.
1240             initializedGlobalHandlers = true;
1241         }
1242         for (LoggerContext cx : contexts()) {
1243             Enumeration<String> enum_ = cx.getLoggerNames();
1244             while (enum_.hasMoreElements()) {
1245                 String name = enum_.nextElement();
1246                 Logger logger = cx.findLogger(name);
1247                 if (logger != null) {
1248                     resetLogger(logger);
1249                 }
1250             }
1251         }

1252     }
1253 
1254     // Private method to reset an individual target logger.
1255     private void resetLogger(Logger logger) {
1256         // Close all the Logger's handlers.
1257         Handler[] targets = logger.getHandlers();
1258         for (Handler h : targets) {
1259             logger.removeHandler(h);
1260             try {
1261                 h.close();
1262             } catch (Exception ex) {
1263                 // Problems closing a handler?  Keep going...
1264             }
1265         }
1266         String name = logger.getName();
1267         if (name != null && name.equals("")) {
1268             // This is the root logger.
1269             logger.setLevel(defaultLevel);
1270         } else {
1271             logger.setLevel(null);




  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 
  27 package java.util.logging;
  28 
  29 import java.io.*;
  30 import java.util.*;
  31 import java.security.*;
  32 import java.lang.ref.ReferenceQueue;
  33 import java.lang.ref.WeakReference;
  34 import java.util.concurrent.CopyOnWriteArrayList;
  35 import sun.misc.JavaAWTAccess;
  36 import sun.misc.SharedSecrets;
  37 
  38 /**
  39  * There is a single global LogManager object that is used to
  40  * maintain a set of shared state about Loggers and log services.
  41  * <p>
  42  * This LogManager object:
  43  * <ul>
  44  * <li> Manages a hierarchical namespace of Logger objects.  All
  45  *      named Loggers are stored in this namespace.
  46  * <li> Manages a set of logging control properties.  These are
  47  *      simple key-value pairs that can be used by Handlers and
  48  *      other logging objects to configure themselves.
  49  * </ul>
  50  * <p>
  51  * The global LogManager object can be retrieved using LogManager.getLogManager().
  52  * The LogManager object is created during class initialization and
  53  * cannot subsequently be changed.
  54  * <p>


  84  * <p>
  85  * The properties for loggers and Handlers will have names starting
  86  * with the dot-separated name for the handler or logger.
  87  * <p>
  88  * The global logging properties may include:
  89  * <ul>
  90  * <li>A property "handlers".  This defines a whitespace or comma separated
  91  * list of class names for handler classes to load and register as
  92  * handlers on the root Logger (the Logger named "").  Each class
  93  * name must be for a Handler class which has a default constructor.
  94  * Note that these Handlers may be created lazily, when they are
  95  * first used.
  96  *
  97  * <li>A property "&lt;logger&gt;.handlers". This defines a whitespace or
  98  * comma separated list of class names for handlers classes to
  99  * load and register as handlers to the specified logger. Each class
 100  * name must be for a Handler class which has a default constructor.
 101  * Note that these Handlers may be created lazily, when they are
 102  * first used.
 103  *
 104  * <li>A property "&lt;logger&gt;.handlers.ensureCloseOnReset". This defines a
 105  * a boolean value. If "&lt;logger&gt;.handlers" is not defined or is empty,
 106  * this property is ignored. Otherwise it defaults to {@code true}. When the
 107  * value is {@code true}, the handlers associated with the logger are guaranteed
 108  * to be closed on {@linkplain reset} and shutdown. This can be turned off
 109  * by explicitly setting "&lt;logger&gt;.handlers.ensureCloseOnReset=false" in
 110  * the configuration. Note that turning this property off causes the risk of
 111  * introducing a resource leak, as the logger may get garbage collected before
 112  * {@code reset()} is called, thus preventing its handlers from being closed
 113  * on {@code reset()}. In that case it is the responsibility of the application
 114  * to ensure that the handlers are closed before the logger is garbage
 115  * collected.
 116  *
 117  * <li>A property "&lt;logger&gt;.useParentHandlers". This defines a boolean
 118  * value. By default every logger calls its parent in addition to
 119  * handling the logging message itself, this often result in messages
 120  * being handled by the root logger as well. When setting this property
 121  * to false a Handler needs to be configured for this logger otherwise
 122  * no logging messages are delivered.
 123  *
 124  * <li>A property "config".  This property is intended to allow
 125  * arbitrary configuration code to be run.  The property defines a
 126  * whitespace or comma separated list of class names.  A new instance will be
 127  * created for each named class.  The default constructor of each class
 128  * may execute arbitrary code to update the logging configuration, such as
 129  * setting logger levels, adding handlers, adding filters, etc.
 130  * </ul>
 131  * <p>
 132  * Note that all classes loaded during LogManager configuration are
 133  * first searched on the system class path before any user class path.
 134  * That includes the LogManager class, any config classes, and any
 135  * handler classes.
 136  * <p>


 166     private volatile Properties props = new Properties();
 167     private final static Level defaultLevel = Level.INFO;
 168 
 169     // LoggerContext for system loggers and user loggers
 170     private final LoggerContext systemContext = new SystemLoggerContext();
 171     private final LoggerContext userContext = new LoggerContext();
 172     // non final field - make it volatile to make sure that other threads
 173     // will see the new value once ensureLogManagerInitialized() has finished
 174     // executing.
 175     private volatile Logger rootLogger;
 176     // Have we done the primordial reading of the configuration file?
 177     // (Must be done after a suitable amount of java.lang.System
 178     // initialization has been done)
 179     private volatile boolean readPrimordialConfiguration;
 180     // Have we initialized global (root) handlers yet?
 181     // This gets set to false in readConfiguration
 182     private boolean initializedGlobalHandlers = true;
 183     // True if JVM death is imminent and the exit hook has been called.
 184     private boolean deathImminent;
 185 
 186     // This list contains the loggers for which some handlers have been
 187     // explicitly configured in the configuration file.
 188     // It prevents these loggers from being arbitrarily garbage collected.
 189     private static final class CloseOnReset {
 190         private final Logger logger;
 191         private CloseOnReset(Logger ref) {
 192             this.logger = Objects.requireNonNull(ref);
 193         }
 194         @Override
 195         public boolean equals(Object other) {
 196             return (other instanceof CloseOnReset) && ((CloseOnReset)other).logger == logger;
 197         }
 198         @Override
 199         public int hashCode() {
 200             return System.identityHashCode(logger);
 201         }
 202         public Logger get() {
 203             return logger;
 204         }
 205         public static CloseOnReset create(Logger logger) {
 206             return new CloseOnReset(logger);
 207         }
 208     }
 209     private final CopyOnWriteArrayList<CloseOnReset> closeOnResetLoggers =
 210             new CopyOnWriteArrayList<>();
 211 
 212 
 213     private final Map<Object, Runnable> listeners =
 214             Collections.synchronizedMap(new IdentityHashMap<>());
 215 
 216     static {
 217         manager = AccessController.doPrivileged(new PrivilegedAction<LogManager>() {
 218             @Override
 219             public LogManager run() {
 220                 LogManager mgr = null;
 221                 String cname = null;
 222                 try {
 223                     cname = System.getProperty("java.util.logging.manager");
 224                     if (cname != null) {
 225                         try {
 226                             Class<?> clz = ClassLoader.getSystemClassLoader()
 227                                     .loadClass(cname);
 228                             mgr = (LogManager) clz.newInstance();
 229                         } catch (ClassNotFoundException ex) {
 230                             Class<?> clz = Thread.currentThread()
 231                                     .getContextClassLoader().loadClass(cname);
 232                             mgr = (LogManager) clz.newInstance();
 233                         }
 234                     }
 235                 } catch (Exception ex) {
 236                     System.err.println("Could not load Logmanager \"" + cname + "\"");
 237                     ex.printStackTrace();
 238                 }
 239                 if (mgr == null) {
 240                     mgr = new LogManager();
 241                 }
 242                 return mgr;
 243 
 244             }
 245         });
 246     }
 247 

 248     // This private class is used as a shutdown hook.
 249     // It does a "reset" to close all open handlers.
 250     private class Cleaner extends Thread {
 251 
 252         private Cleaner() {
 253             /* Set context class loader to null in order to avoid
 254              * keeping a strong reference to an application classloader.
 255              */
 256             this.setContextClassLoader(null);
 257         }
 258 
 259         @Override
 260         public void run() {
 261             // This is to ensure the LogManager.<clinit> is completed
 262             // before synchronized block. Otherwise deadlocks are possible.
 263             LogManager mgr = manager;
 264 
 265             // If the global handlers haven't been initialized yet, we
 266             // don't want to initialize them just so we can close them!
 267             synchronized (LogManager.this) {


 898                         // we'll just loop around and try again.
 899                         result = findLogger(name);
 900                     }
 901                 } while (result == null);
 902             }
 903             return result;
 904         }
 905     }
 906 
 907     // Add new per logger handlers.
 908     // We need to raise privilege here. All our decisions will
 909     // be made based on the logging configuration, which can
 910     // only be modified by trusted code.
 911     private void loadLoggerHandlers(final Logger logger, final String name,
 912                                     final String handlersPropertyName)
 913     {
 914         AccessController.doPrivileged(new PrivilegedAction<Object>() {
 915             @Override
 916             public Object run() {
 917                 String names[] = parseClassNames(handlersPropertyName);
 918                 final boolean ensureCloseOnReset = names.length > 0
 919                         && getBooleanProperty(
 920                                 handlersPropertyName + ".ensureCloseOnReset",
 921                                 true);
 922                 int count = 0;
 923                 for (String type : names) {
 924                     try {
 925                         Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(type);
 926                         Handler hdl = (Handler) clz.newInstance();
 927                         // Check if there is a property defining the
 928                         // this handler's level.
 929                         String levs = getProperty(type + ".level");
 930                         if (levs != null) {
 931                             Level l = Level.findLevel(levs);
 932                             if (l != null) {
 933                                 hdl.setLevel(l);
 934                             } else {
 935                                 // Probably a bad level. Drop through.
 936                                 System.err.println("Can't set level for " + type);
 937                             }
 938                         }
 939                         // Add this Handler to the logger
 940                         logger.addHandler(hdl);
 941                         if (++count == 1 && ensureCloseOnReset) {
 942                             // add this logger to the closeOnResetLoggers list.
 943                             closeOnResetLoggers.addIfAbsent(CloseOnReset.create(logger));
 944                         }
 945                     } catch (Exception ex) {
 946                         System.err.println("Can't load log handler \"" + type + "\"");
 947                         System.err.println("" + ex);
 948                         ex.printStackTrace();
 949                     }
 950                 }
 951 
 952                 return null;
 953             }
 954         });
 955     }
 956 
 957 
 958     // loggerRefQueue holds LoggerWeakRef objects for Logger objects
 959     // that have been GC'ed.
 960     private final ReferenceQueue<Logger> loggerRefQueue
 961         = new ReferenceQueue<>();
 962 
 963     // Package-level inner class.
 964     // Helper class for managing WeakReferences to Logger objects.
 965     //
 966     // LogManager.namedLoggers
 967     //     - has weak references to all named Loggers
 968     //     - namedLoggers keeps the LoggerWeakRef objects for the named
 969     //       Loggers around until we can deal with the book keeping for
 970     //       the named Logger that is being GC'ed.
 971     // LogManager.LogNode.loggerRef


1266         }
1267         try (final InputStream in = new FileInputStream(fname)) {
1268             final BufferedInputStream bin = new BufferedInputStream(in);
1269             readConfiguration(bin);
1270         }
1271     }
1272 
1273     /**
1274      * Reset the logging configuration.
1275      * <p>
1276      * For all named loggers, the reset operation removes and closes
1277      * all Handlers and (except for the root logger) sets the level
1278      * to null.  The root logger's level is set to Level.INFO.
1279      *
1280      * @exception  SecurityException  if a security manager exists and if
1281      *             the caller does not have LoggingPermission("control").
1282      */
1283 
1284     public void reset() throws SecurityException {
1285         checkPermission();
1286         List<CloseOnReset> persistent;
1287         synchronized (this) {
1288             props = new Properties();
1289             // make sure we keep the loggers persistent until reset is done.
1290             // Those are the loggers for which we previously created a
1291             // handler from the configuration, and we need to prevent them
1292             // from being gc'ed until those handlers are closed.
1293             persistent = new ArrayList<>(closeOnResetLoggers);
1294             closeOnResetLoggers.clear();
1295             // Since we are doing a reset we no longer want to initialize
1296             // the global handlers, if they haven't been initialized yet.
1297             initializedGlobalHandlers = true;
1298         }
1299         for (LoggerContext cx : contexts()) {
1300             Enumeration<String> enum_ = cx.getLoggerNames();
1301             while (enum_.hasMoreElements()) {
1302                 String name = enum_.nextElement();
1303                 Logger logger = cx.findLogger(name);
1304                 if (logger != null) {
1305                     resetLogger(logger);
1306                 }
1307             }
1308         }
1309         persistent.clear();
1310     }
1311 
1312     // Private method to reset an individual target logger.
1313     private void resetLogger(Logger logger) {
1314         // Close all the Logger's handlers.
1315         Handler[] targets = logger.getHandlers();
1316         for (Handler h : targets) {
1317             logger.removeHandler(h);
1318             try {
1319                 h.close();
1320             } catch (Exception ex) {
1321                 // Problems closing a handler?  Keep going...
1322             }
1323         }
1324         String name = logger.getName();
1325         if (name != null && name.equals("")) {
1326             // This is the root logger.
1327             logger.setLevel(defaultLevel);
1328         } else {
1329             logger.setLevel(null);


< prev index next >