1138 * Checks if a message of the given level would be logged by 1139 * this logger. 1140 * 1141 * @param level the log message level. 1142 * @return {@code true} if the given log message level is currently 1143 * being logged. 1144 * 1145 * @throws NullPointerException if {@code level} is {@code null}. 1146 */ 1147 public boolean isLoggable(Level level); 1148 1149 /** 1150 * Logs a message. 1151 * 1152 * @implSpec The default implementation for this method calls 1153 * {@code this.log(level, (ResourceBundle)null, msg, (Object[])null);} 1154 * 1155 * @param level the log message level. 1156 * @param msg the string message (or a key in the message catalog, if 1157 * this logger is a {@link 1158 * LoggerFinder#getLocalizedLogger(java.lang.String, java.util.ResourceBundle, java.lang.Class) 1159 * localized logger}); can be {@code null}. 1160 * 1161 * @throws NullPointerException if {@code level} is {@code null}. 1162 */ 1163 public default void log(Level level, String msg) { 1164 log(level, (ResourceBundle) null, msg, (Object[]) null); 1165 } 1166 1167 /** 1168 * Logs a lazily supplied message. 1169 * <p> 1170 * If the logger is currently enabled for the given log message level 1171 * then a message is logged that is the result produced by the 1172 * given supplier function. Otherwise, the supplier is not operated on. 1173 * 1174 * @implSpec When logging is enabled for the given level, the default 1175 * implementation for this method calls 1176 * {@code this.log(level, (ResourceBundle)null, msgSupplier.get(), (Object[])null);} 1177 * 1178 * @param level the log message level. 1179 * @param msgSupplier a supplier function that produces a message. 1205 * 1206 * @throws NullPointerException if {@code level} is {@code null}, or 1207 * {@code obj} is {@code null}. 1208 */ 1209 public default void log(Level level, Object obj) { 1210 Objects.requireNonNull(obj); 1211 if (isLoggable(Objects.requireNonNull(level))) { 1212 this.log(level, (ResourceBundle) null, obj.toString(), (Object[]) null); 1213 } 1214 } 1215 1216 /** 1217 * Logs a message associated with a given throwable. 1218 * 1219 * @implSpec The default implementation for this method calls 1220 * {@code this.log(level, (ResourceBundle)null, msg, thrown);} 1221 * 1222 * @param level the log message level. 1223 * @param msg the string message (or a key in the message catalog, if 1224 * this logger is a {@link 1225 * LoggerFinder#getLocalizedLogger(java.lang.String, java.util.ResourceBundle, java.lang.Class) 1226 * localized logger}); can be {@code null}. 1227 * @param thrown a {@code Throwable} associated with the log message; 1228 * can be {@code null}. 1229 * 1230 * @throws NullPointerException if {@code level} is {@code null}. 1231 */ 1232 public default void log(Level level, String msg, Throwable thrown) { 1233 this.log(level, null, msg, thrown); 1234 } 1235 1236 /** 1237 * Logs a lazily supplied message associated with a given throwable. 1238 * <p> 1239 * If the logger is currently enabled for the given log message level 1240 * then a message is logged that is the result produced by the 1241 * given supplier function. Otherwise, the supplier is not operated on. 1242 * 1243 * @implSpec When logging is enabled for the given level, the default 1244 * implementation for this method calls 1245 * {@code this.log(level, (ResourceBundle)null, msgSupplier.get(), thrown);} 1246 * 1253 * {@code msgSupplier} is {@code null}. 1254 */ 1255 public default void log(Level level, Supplier<String> msgSupplier, 1256 Throwable thrown) { 1257 Objects.requireNonNull(msgSupplier); 1258 if (isLoggable(Objects.requireNonNull(level))) { 1259 this.log(level, null, msgSupplier.get(), thrown); 1260 } 1261 } 1262 1263 /** 1264 * Logs a message with an optional list of parameters. 1265 * 1266 * @implSpec The default implementation for this method calls 1267 * {@code this.log(level, (ResourceBundle)null, format, params);} 1268 * 1269 * @param level one of the log message level identifiers. 1270 * @param format the string message format in {@link 1271 * java.text.MessageFormat} format, (or a key in the message 1272 * catalog, if this logger is a {@link 1273 * LoggerFinder#getLocalizedLogger(java.lang.String, java.util.ResourceBundle, java.lang.Class) 1274 * localized logger}); can be {@code null}. 1275 * @param params an optional list of parameters to the message (may be 1276 * none). 1277 * 1278 * @throws NullPointerException if {@code level} is {@code null}. 1279 */ 1280 public default void log(Level level, String format, Object... params) { 1281 this.log(level, null, format, params); 1282 } 1283 1284 /** 1285 * Logs a localized message associated with a given throwable. 1286 * <p> 1287 * If the given resource bundle is non-{@code null}, the {@code msg} 1288 * string is localized using the given resource bundle. 1289 * Otherwise the {@code msg} string is not localized. 1290 * 1291 * @param level the log message level. 1292 * @param bundle a resource bundle to localize {@code msg}; can be 1293 * {@code null}. 1294 * @param msg the string message (or a key in the message catalog, 1436 * {@code RuntimePermission("loggerFinder")}. 1437 */ 1438 protected LoggerFinder() { 1439 this(checkPermission()); 1440 } 1441 1442 private LoggerFinder(Void unused) { 1443 // nothing to do. 1444 } 1445 1446 private static Void checkPermission() { 1447 final SecurityManager sm = System.getSecurityManager(); 1448 if (sm != null) { 1449 sm.checkPermission(LOGGERFINDER_PERMISSION); 1450 } 1451 return null; 1452 } 1453 1454 /** 1455 * Returns an instance of {@link Logger Logger} 1456 * for the given {@code caller}. 1457 * 1458 * @param name the name of the logger. 1459 * @param caller the class for which the logger is being requested. 1460 * 1461 * @return a {@link Logger logger} suitable for the given caller's 1462 * use. 1463 * @throws NullPointerException if {@code name} is {@code null} or 1464 * {@code caller} is {@code null}. 1465 * @throws SecurityException if a security manager is present and its 1466 * {@code checkPermission} method doesn't allow the 1467 * {@code RuntimePermission("loggerFinder")}. 1468 */ 1469 public abstract Logger getLogger(String name, /* Module */ Class<?> caller); 1470 1471 /** 1472 * Returns a localizable instance of {@link Logger Logger} 1473 * for the given {@code caller}. 1474 * The returned logger will use the provided resource bundle for 1475 * message localization. 1476 * 1477 * @implSpec By default, this method calls {@link 1478 * #getLogger(java.lang.String, java.lang.Class) 1479 * this.getLogger(name, caller)} to obtain a logger, then wraps that 1480 * logger in a {@link Logger} instance where all methods that do not 1481 * take a {@link ResourceBundle} as parameter are redirected to one 1482 * which does - passing the given {@code bundle} for 1483 * localization. So for instance, a call to {@link 1484 * Logger#log(Level, String) Logger.log(Level.INFO, msg)} 1485 * will end up as a call to {@link 1486 * Logger#log(Level, ResourceBundle, String, Object...) 1487 * Logger.log(Level.INFO, bundle, msg, (Object[])null)} on the wrapped 1488 * logger instance. 1489 * Note however that by default, string messages returned by {@link 1490 * java.util.function.Supplier Supplier<String>} will not be 1491 * localized, as it is assumed that such strings are messages which are 1492 * already constructed, rather than keys in a resource bundle. 1493 * <p> 1494 * An implementation of {@code LoggerFinder} may override this method, 1495 * for example, when the underlying logging backend provides its own 1496 * mechanism for localizing log messages, then such a 1497 * {@code LoggerFinder} would be free to return a logger 1498 * that makes direct use of the mechanism provided by the backend. 1499 * 1500 * @param name the name of the logger. 1501 * @param bundle a resource bundle; can be {@code null}. 1502 * @param caller the class for which the logger is being requested. 1503 * @return an instance of {@link Logger Logger} which will use the 1504 * provided resource bundle for message localization. 1505 * 1506 * @throws NullPointerException if {@code name} is {@code null} or 1507 * {@code caller} is {@code null}. 1508 * @throws SecurityException if a security manager is present and its 1509 * {@code checkPermission} method doesn't allow the 1510 * {@code RuntimePermission("loggerFinder")}. 1511 */ 1512 public Logger getLocalizedLogger(String name, ResourceBundle bundle, 1513 /* Module */ Class<?> caller) { 1514 return new LocalizedLoggerWrapper<>(getLogger(name, caller), bundle); 1515 } 1516 1517 /** 1518 * Returns the {@code LoggerFinder} instance. There is one 1519 * single system-wide {@code LoggerFinder} instance in 1520 * the Java Runtime. See the class specification of how the 1521 * {@link LoggerFinder LoggerFinder} implementation is located and 1522 * loaded. 1523 1524 * @return the {@link LoggerFinder LoggerFinder} instance. 1525 * @throws SecurityException if a security manager is present and its 1526 * {@code checkPermission} method doesn't allow the 1527 * {@code RuntimePermission("loggerFinder")}. 1528 */ 1529 public static LoggerFinder getLoggerFinder() { 1530 final SecurityManager sm = System.getSecurityManager(); 1531 if (sm != null) { 1532 sm.checkPermission(LOGGERFINDER_PERMISSION); 1533 } 1534 return accessProvider(); 1541 // always return the same instance, so if we don't have it, 1542 // just fetch it again. 1543 if (service == null) { 1544 PrivilegedAction<LoggerFinder> pa = 1545 () -> LoggerFinderLoader.getLoggerFinder(); 1546 service = AccessController.doPrivileged(pa, null, 1547 LOGGERFINDER_PERMISSION); 1548 } 1549 return service; 1550 } 1551 1552 } 1553 1554 1555 /** 1556 * Returns an instance of {@link Logger Logger} for the caller's 1557 * use. 1558 * 1559 * @implSpec 1560 * Instances returned by this method route messages to loggers 1561 * obtained by calling {@link LoggerFinder#getLogger(java.lang.String, java.lang.Class) 1562 * LoggerFinder.getLogger(name, caller)}. 1563 * 1564 * @apiNote 1565 * This method may defer calling the {@link 1566 * LoggerFinder#getLogger(java.lang.String, java.lang.Class) 1567 * LoggerFinder.getLogger} method to create an actual logger supplied by 1568 * the logging backend, for instance, to allow loggers to be obtained during 1569 * the system initialization time. 1570 * 1571 * @param name the name of the logger. 1572 * @return an instance of {@link Logger} that can be used by the calling 1573 * class. 1574 * @throws NullPointerException if {@code name} is {@code null}. 1575 * 1576 * @since 9 1577 */ 1578 @CallerSensitive 1579 public static Logger getLogger(String name) { 1580 Objects.requireNonNull(name); 1581 final Class<?> caller = Reflection.getCallerClass(); 1582 return LazyLoggers.getLogger(name, caller); 1583 } 1584 1585 /** 1586 * Returns a localizable instance of {@link Logger 1587 * Logger} for the caller's use. 1588 * The returned logger will use the provided resource bundle for message 1589 * localization. 1590 * 1591 * @implSpec 1592 * The returned logger will perform message localization as specified 1593 * by {@link LoggerFinder#getLocalizedLogger(java.lang.String, 1594 * java.util.ResourceBundle, java.lang.Class) 1595 * LoggerFinder.getLocalizedLogger(name, bundle, caller}. 1596 * 1597 * @apiNote 1598 * This method is intended to be used after the system is fully initialized. 1599 * This method may trigger the immediate loading and initialization 1600 * of the {@link LoggerFinder} service, which may cause issues if the 1601 * Java Runtime is not ready to initialize the concrete service 1602 * implementation yet. 1603 * System classes which may be loaded early in the boot sequence and 1604 * need to log localized messages should create a logger using 1605 * {@link #getLogger(java.lang.String)} and then use the log methods that 1606 * take a resource bundle as parameter. 1607 * 1608 * @param name the name of the logger. 1609 * @param bundle a resource bundle. 1610 * @return an instance of {@link Logger} which will use the provided 1611 * resource bundle for message localization. 1612 * @throws NullPointerException if {@code name} is {@code null} or 1613 * {@code bundle} is {@code null}. 1614 * 1615 * @since 9 1616 */ 1617 @CallerSensitive 1618 public static Logger getLogger(String name, ResourceBundle bundle) { 1619 final ResourceBundle rb = Objects.requireNonNull(bundle); 1620 Objects.requireNonNull(name); 1621 final Class<?> caller = Reflection.getCallerClass(); 1622 final SecurityManager sm = System.getSecurityManager(); 1623 // We don't use LazyLoggers if a resource bundle is specified. 1624 // Bootstrap sensitive classes in the JDK do not use resource bundles 1625 // when logging. This could be revisited later, if it needs to. 1626 if (sm != null) { 1627 return AccessController.doPrivileged((PrivilegedAction<Logger>) 1628 () -> LoggerFinder.accessProvider().getLocalizedLogger(name, rb, caller), 1629 null, 1630 LoggerFinder.LOGGERFINDER_PERMISSION); 1631 } 1632 return LoggerFinder.accessProvider().getLocalizedLogger(name, rb, caller); 1633 } 1634 1635 /** 1636 * Terminates the currently running Java Virtual Machine. The 1637 * argument serves as a status code; by convention, a nonzero status 1638 * code indicates abnormal termination. 1639 * <p> 1640 * This method calls the <code>exit</code> method in class 1641 * <code>Runtime</code>. This method never returns normally. 1642 * <p> 1643 * The call <code>System.exit(n)</code> is effectively equivalent to 1644 * the call: 1645 * <blockquote><pre> 1646 * Runtime.getRuntime().exit(n) 1647 * </pre></blockquote> 1648 * 1649 * @param status exit status. 1650 * @throws SecurityException 1651 * if a security manager exists and its <code>checkExit</code> 1652 * method doesn't allow exit with the specified status. | 1138 * Checks if a message of the given level would be logged by 1139 * this logger. 1140 * 1141 * @param level the log message level. 1142 * @return {@code true} if the given log message level is currently 1143 * being logged. 1144 * 1145 * @throws NullPointerException if {@code level} is {@code null}. 1146 */ 1147 public boolean isLoggable(Level level); 1148 1149 /** 1150 * Logs a message. 1151 * 1152 * @implSpec The default implementation for this method calls 1153 * {@code this.log(level, (ResourceBundle)null, msg, (Object[])null);} 1154 * 1155 * @param level the log message level. 1156 * @param msg the string message (or a key in the message catalog, if 1157 * this logger is a {@link 1158 * LoggerFinder#getLocalizedLogger(java.lang.String, 1159 * java.util.ResourceBundle, java.lang.reflect.Module) localized logger}); 1160 * can be {@code null}. 1161 * 1162 * @throws NullPointerException if {@code level} is {@code null}. 1163 */ 1164 public default void log(Level level, String msg) { 1165 log(level, (ResourceBundle) null, msg, (Object[]) null); 1166 } 1167 1168 /** 1169 * Logs a lazily supplied message. 1170 * <p> 1171 * If the logger is currently enabled for the given log message level 1172 * then a message is logged that is the result produced by the 1173 * given supplier function. Otherwise, the supplier is not operated on. 1174 * 1175 * @implSpec When logging is enabled for the given level, the default 1176 * implementation for this method calls 1177 * {@code this.log(level, (ResourceBundle)null, msgSupplier.get(), (Object[])null);} 1178 * 1179 * @param level the log message level. 1180 * @param msgSupplier a supplier function that produces a message. 1206 * 1207 * @throws NullPointerException if {@code level} is {@code null}, or 1208 * {@code obj} is {@code null}. 1209 */ 1210 public default void log(Level level, Object obj) { 1211 Objects.requireNonNull(obj); 1212 if (isLoggable(Objects.requireNonNull(level))) { 1213 this.log(level, (ResourceBundle) null, obj.toString(), (Object[]) null); 1214 } 1215 } 1216 1217 /** 1218 * Logs a message associated with a given throwable. 1219 * 1220 * @implSpec The default implementation for this method calls 1221 * {@code this.log(level, (ResourceBundle)null, msg, thrown);} 1222 * 1223 * @param level the log message level. 1224 * @param msg the string message (or a key in the message catalog, if 1225 * this logger is a {@link 1226 * LoggerFinder#getLocalizedLogger(java.lang.String, 1227 * java.util.ResourceBundle, java.lang.reflect.Module) localized logger}); 1228 * can be {@code null}. 1229 * @param thrown a {@code Throwable} associated with the log message; 1230 * can be {@code null}. 1231 * 1232 * @throws NullPointerException if {@code level} is {@code null}. 1233 */ 1234 public default void log(Level level, String msg, Throwable thrown) { 1235 this.log(level, null, msg, thrown); 1236 } 1237 1238 /** 1239 * Logs a lazily supplied message associated with a given throwable. 1240 * <p> 1241 * If the logger is currently enabled for the given log message level 1242 * then a message is logged that is the result produced by the 1243 * given supplier function. Otherwise, the supplier is not operated on. 1244 * 1245 * @implSpec When logging is enabled for the given level, the default 1246 * implementation for this method calls 1247 * {@code this.log(level, (ResourceBundle)null, msgSupplier.get(), thrown);} 1248 * 1255 * {@code msgSupplier} is {@code null}. 1256 */ 1257 public default void log(Level level, Supplier<String> msgSupplier, 1258 Throwable thrown) { 1259 Objects.requireNonNull(msgSupplier); 1260 if (isLoggable(Objects.requireNonNull(level))) { 1261 this.log(level, null, msgSupplier.get(), thrown); 1262 } 1263 } 1264 1265 /** 1266 * Logs a message with an optional list of parameters. 1267 * 1268 * @implSpec The default implementation for this method calls 1269 * {@code this.log(level, (ResourceBundle)null, format, params);} 1270 * 1271 * @param level one of the log message level identifiers. 1272 * @param format the string message format in {@link 1273 * java.text.MessageFormat} format, (or a key in the message 1274 * catalog, if this logger is a {@link 1275 * LoggerFinder#getLocalizedLogger(java.lang.String, 1276 * java.util.ResourceBundle, java.lang.reflect.Module) localized logger}); 1277 * can be {@code null}. 1278 * @param params an optional list of parameters to the message (may be 1279 * none). 1280 * 1281 * @throws NullPointerException if {@code level} is {@code null}. 1282 */ 1283 public default void log(Level level, String format, Object... params) { 1284 this.log(level, null, format, params); 1285 } 1286 1287 /** 1288 * Logs a localized message associated with a given throwable. 1289 * <p> 1290 * If the given resource bundle is non-{@code null}, the {@code msg} 1291 * string is localized using the given resource bundle. 1292 * Otherwise the {@code msg} string is not localized. 1293 * 1294 * @param level the log message level. 1295 * @param bundle a resource bundle to localize {@code msg}; can be 1296 * {@code null}. 1297 * @param msg the string message (or a key in the message catalog, 1439 * {@code RuntimePermission("loggerFinder")}. 1440 */ 1441 protected LoggerFinder() { 1442 this(checkPermission()); 1443 } 1444 1445 private LoggerFinder(Void unused) { 1446 // nothing to do. 1447 } 1448 1449 private static Void checkPermission() { 1450 final SecurityManager sm = System.getSecurityManager(); 1451 if (sm != null) { 1452 sm.checkPermission(LOGGERFINDER_PERMISSION); 1453 } 1454 return null; 1455 } 1456 1457 /** 1458 * Returns an instance of {@link Logger Logger} 1459 * for the given {@code module}. 1460 * 1461 * @param name the name of the logger. 1462 * @param module the module for which the logger is being requested. 1463 * 1464 * @return a {@link Logger logger} suitable for use within the given 1465 * module. 1466 * @throws NullPointerException if {@code name} is {@code null} or 1467 * {@code module} is {@code null}. 1468 * @throws SecurityException if a security manager is present and its 1469 * {@code checkPermission} method doesn't allow the 1470 * {@code RuntimePermission("loggerFinder")}. 1471 */ 1472 public abstract Logger getLogger(String name, Module module); 1473 1474 /** 1475 * Returns a localizable instance of {@link Logger Logger} 1476 * for the given {@code module}. 1477 * The returned logger will use the provided resource bundle for 1478 * message localization. 1479 * 1480 * @implSpec By default, this method calls {@link 1481 * #getLogger(java.lang.String, java.lang.reflect.Module) 1482 * this.getLogger(name, module)} to obtain a logger, then wraps that 1483 * logger in a {@link Logger} instance where all methods that do not 1484 * take a {@link ResourceBundle} as parameter are redirected to one 1485 * which does - passing the given {@code bundle} for 1486 * localization. So for instance, a call to {@link 1487 * Logger#log(Level, String) Logger.log(Level.INFO, msg)} 1488 * will end up as a call to {@link 1489 * Logger#log(Level, ResourceBundle, String, Object...) 1490 * Logger.log(Level.INFO, bundle, msg, (Object[])null)} on the wrapped 1491 * logger instance. 1492 * Note however that by default, string messages returned by {@link 1493 * java.util.function.Supplier Supplier<String>} will not be 1494 * localized, as it is assumed that such strings are messages which are 1495 * already constructed, rather than keys in a resource bundle. 1496 * <p> 1497 * An implementation of {@code LoggerFinder} may override this method, 1498 * for example, when the underlying logging backend provides its own 1499 * mechanism for localizing log messages, then such a 1500 * {@code LoggerFinder} would be free to return a logger 1501 * that makes direct use of the mechanism provided by the backend. 1502 * 1503 * @param name the name of the logger. 1504 * @param bundle a resource bundle; can be {@code null}. 1505 * @param module the module for which the logger is being requested. 1506 * @return an instance of {@link Logger Logger} which will use the 1507 * provided resource bundle for message localization. 1508 * 1509 * @throws NullPointerException if {@code name} is {@code null} or 1510 * {@code module} is {@code null}. 1511 * @throws SecurityException if a security manager is present and its 1512 * {@code checkPermission} method doesn't allow the 1513 * {@code RuntimePermission("loggerFinder")}. 1514 */ 1515 public Logger getLocalizedLogger(String name, ResourceBundle bundle, 1516 Module module) { 1517 return new LocalizedLoggerWrapper<>(getLogger(name, module), bundle); 1518 } 1519 1520 /** 1521 * Returns the {@code LoggerFinder} instance. There is one 1522 * single system-wide {@code LoggerFinder} instance in 1523 * the Java Runtime. See the class specification of how the 1524 * {@link LoggerFinder LoggerFinder} implementation is located and 1525 * loaded. 1526 1527 * @return the {@link LoggerFinder LoggerFinder} instance. 1528 * @throws SecurityException if a security manager is present and its 1529 * {@code checkPermission} method doesn't allow the 1530 * {@code RuntimePermission("loggerFinder")}. 1531 */ 1532 public static LoggerFinder getLoggerFinder() { 1533 final SecurityManager sm = System.getSecurityManager(); 1534 if (sm != null) { 1535 sm.checkPermission(LOGGERFINDER_PERMISSION); 1536 } 1537 return accessProvider(); 1544 // always return the same instance, so if we don't have it, 1545 // just fetch it again. 1546 if (service == null) { 1547 PrivilegedAction<LoggerFinder> pa = 1548 () -> LoggerFinderLoader.getLoggerFinder(); 1549 service = AccessController.doPrivileged(pa, null, 1550 LOGGERFINDER_PERMISSION); 1551 } 1552 return service; 1553 } 1554 1555 } 1556 1557 1558 /** 1559 * Returns an instance of {@link Logger Logger} for the caller's 1560 * use. 1561 * 1562 * @implSpec 1563 * Instances returned by this method route messages to loggers 1564 * obtained by calling {@link LoggerFinder#getLogger(java.lang.String, 1565 * java.lang.reflect.Module) LoggerFinder.getLogger(name, module)}, where 1566 * {@code module} is the caller's module. 1567 * 1568 * @apiNote 1569 * This method may defer calling the {@link 1570 * LoggerFinder#getLogger(java.lang.String, java.lang.reflect.Module) 1571 * LoggerFinder.getLogger} method to create an actual logger supplied by 1572 * the logging backend, for instance, to allow loggers to be obtained during 1573 * the system initialization time. 1574 * 1575 * @param name the name of the logger. 1576 * @return an instance of {@link Logger} that can be used by the calling 1577 * class. 1578 * @throws NullPointerException if {@code name} is {@code null}. 1579 * 1580 * @since 9 1581 */ 1582 @CallerSensitive 1583 public static Logger getLogger(String name) { 1584 Objects.requireNonNull(name); 1585 final Class<?> caller = Reflection.getCallerClass(); 1586 return LazyLoggers.getLogger(name, caller.getModule()); 1587 } 1588 1589 /** 1590 * Returns a localizable instance of {@link Logger 1591 * Logger} for the caller's use. 1592 * The returned logger will use the provided resource bundle for message 1593 * localization. 1594 * 1595 * @implSpec 1596 * The returned logger will perform message localization as specified 1597 * by {@link LoggerFinder#getLocalizedLogger(java.lang.String, 1598 * java.util.ResourceBundle, java.lang.reflect.Module) 1599 * LoggerFinder.getLocalizedLogger(name, bundle, module}, where 1600 * {@code module} is the caller's module. 1601 * 1602 * @apiNote 1603 * This method is intended to be used after the system is fully initialized. 1604 * This method may trigger the immediate loading and initialization 1605 * of the {@link LoggerFinder} service, which may cause issues if the 1606 * Java Runtime is not ready to initialize the concrete service 1607 * implementation yet. 1608 * System classes which may be loaded early in the boot sequence and 1609 * need to log localized messages should create a logger using 1610 * {@link #getLogger(java.lang.String)} and then use the log methods that 1611 * take a resource bundle as parameter. 1612 * 1613 * @param name the name of the logger. 1614 * @param bundle a resource bundle. 1615 * @return an instance of {@link Logger} which will use the provided 1616 * resource bundle for message localization. 1617 * @throws NullPointerException if {@code name} is {@code null} or 1618 * {@code bundle} is {@code null}. 1619 * 1620 * @since 9 1621 */ 1622 @CallerSensitive 1623 public static Logger getLogger(String name, ResourceBundle bundle) { 1624 final ResourceBundle rb = Objects.requireNonNull(bundle); 1625 Objects.requireNonNull(name); 1626 final Class<?> caller = Reflection.getCallerClass(); 1627 final SecurityManager sm = System.getSecurityManager(); 1628 // We don't use LazyLoggers if a resource bundle is specified. 1629 // Bootstrap sensitive classes in the JDK do not use resource bundles 1630 // when logging. This could be revisited later, if it needs to. 1631 if (sm != null) { 1632 final PrivilegedAction<Logger> pa = 1633 () -> LoggerFinder.accessProvider() 1634 .getLocalizedLogger(name, rb, caller.getModule()); 1635 return AccessController.doPrivileged(pa, null, 1636 LoggerFinder.LOGGERFINDER_PERMISSION); 1637 } 1638 return LoggerFinder.accessProvider() 1639 .getLocalizedLogger(name, rb, caller.getModule()); 1640 } 1641 1642 /** 1643 * Terminates the currently running Java Virtual Machine. The 1644 * argument serves as a status code; by convention, a nonzero status 1645 * code indicates abnormal termination. 1646 * <p> 1647 * This method calls the <code>exit</code> method in class 1648 * <code>Runtime</code>. This method never returns normally. 1649 * <p> 1650 * The call <code>System.exit(n)</code> is effectively equivalent to 1651 * the call: 1652 * <blockquote><pre> 1653 * Runtime.getRuntime().exit(n) 1654 * </pre></blockquote> 1655 * 1656 * @param status exit status. 1657 * @throws SecurityException 1658 * if a security manager exists and its <code>checkExit</code> 1659 * method doesn't allow exit with the specified status. |