提交 bffd72f5 编写于 作者: M mchung

8010309: Improve PlatformLogger.isLoggable performance by direct mapping from an integer to Level

Reviewed-by: mchung
Contributed-by: peter.levart@gmail.com, bourges.laurent@gmail.com
上级 a56820f6
...@@ -27,14 +27,11 @@ ...@@ -27,14 +27,11 @@
package sun.util.logging; package sun.util.logging;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.text.MessageFormat;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
...@@ -87,18 +84,51 @@ import sun.misc.SharedSecrets; ...@@ -87,18 +84,51 @@ import sun.misc.SharedSecrets;
* @since 1.7 * @since 1.7
*/ */
public class PlatformLogger { public class PlatformLogger {
// Same values as java.util.logging.Level for easy mapping // shortcut to PlatformLogger.Level enums
public static final int OFF = Integer.MAX_VALUE; public static final Level OFF = Level.OFF;
public static final int SEVERE = 1000; public static final Level SEVERE = Level.SEVERE;
public static final int WARNING = 900; public static final Level WARNING = Level.WARNING;
public static final int INFO = 800; public static final Level INFO = Level.INFO;
public static final int CONFIG = 700; public static final Level CONFIG = Level.CONFIG;
public static final int FINE = 500; public static final Level FINE = Level.FINE;
public static final int FINER = 400; public static final Level FINER = Level.FINER;
public static final int FINEST = 300; public static final Level FINEST = Level.FINEST;
public static final int ALL = Integer.MIN_VALUE; public static final Level ALL = Level.ALL;
private static final int defaultLevel = INFO; /**
* PlatformLogger logging levels.
*/
public static enum Level {
// The name and value must match that of {@code java.util.logging.Level} objects.
ALL(Integer.MIN_VALUE),
FINEST(300),
FINER(400),
FINE(500),
CONFIG(700),
INFO(800),
WARNING(900),
SEVERE(1000),
OFF(Integer.MAX_VALUE);
/**
* Associated java.util.logging.Level lazily initialized in
* JavaLoggerProxy's static initializer only once
* when java.util.logging is available and enabled.
* Only accessed by JavaLoggerProxy.
*/
/* java.util.logging.Level */ Object javaLevel;
private final int value;
public int intValue() {
return value;
}
Level(int value) {
this.value = value;
}
}
private static final Level DEFAULT_LEVEL = INFO;
private static boolean loggingEnabled; private static boolean loggingEnabled;
static { static {
loggingEnabled = AccessController.doPrivileged( loggingEnabled = AccessController.doPrivileged(
...@@ -109,6 +139,20 @@ public class PlatformLogger { ...@@ -109,6 +139,20 @@ public class PlatformLogger {
return (cname != null || fname != null); return (cname != null || fname != null);
} }
}); });
// force loading of all JavaLoggerProxy (sub)classes to make JIT de-optimizations
// less probable. Don't initialize JavaLoggerProxy class since
// java.util.logging may not be enabled.
try {
Class.forName("sun.util.logging.PlatformLogger$DefaultLoggerProxy",
false,
PlatformLogger.class.getClassLoader());
Class.forName("sun.util.logging.PlatformLogger$JavaLoggerProxy",
false, // do not invoke class initializer
PlatformLogger.class.getClassLoader());
} catch (ClassNotFoundException ex) {
throw new InternalError(ex);
}
} }
// Table of known loggers. Maps names to PlatformLoggers. // Table of known loggers. Maps names to PlatformLoggers.
...@@ -143,27 +187,32 @@ public class PlatformLogger { ...@@ -143,27 +187,32 @@ public class PlatformLogger {
WeakReference<PlatformLogger> ref = entry.getValue(); WeakReference<PlatformLogger> ref = entry.getValue();
PlatformLogger plog = ref.get(); PlatformLogger plog = ref.get();
if (plog != null) { if (plog != null) {
plog.newJavaLogger(); plog.redirectToJavaLoggerProxy();
} }
} }
} }
/** /**
* Creates a new JavaLogger that the platform logger uses * Creates a new JavaLoggerProxy and redirects the platform logger to it
*/ */
private void newJavaLogger() { private void redirectToJavaLoggerProxy() {
logger = new JavaLogger(logger.name, logger.effectiveLevel); DefaultLoggerProxy lp = DefaultLoggerProxy.class.cast(this.loggerProxy);
} JavaLoggerProxy jlp = new JavaLoggerProxy(lp.name, lp.level);
// the order of assignments is important
// logger may be replaced with a JavaLogger object this.javaLoggerProxy = jlp; // isLoggable checks javaLoggerProxy if set
// when the logging facility is enabled this.loggerProxy = jlp;
private volatile LoggerProxy logger; }
// DefaultLoggerProxy may be replaced with a JavaLoggerProxy object
// when the java.util.logging facility is enabled
private volatile LoggerProxy loggerProxy;
// javaLoggerProxy is only set when the java.util.logging facility is enabled
private volatile JavaLoggerProxy javaLoggerProxy;
private PlatformLogger(String name) { private PlatformLogger(String name) {
if (loggingEnabled) { if (loggingEnabled) {
this.logger = new JavaLogger(name); this.loggerProxy = this.javaLoggerProxy = new JavaLoggerProxy(name);
} else { } else {
this.logger = new LoggerProxy(name); this.loggerProxy = new DefaultLoggerProxy(name);
} }
} }
...@@ -172,204 +221,248 @@ public class PlatformLogger { ...@@ -172,204 +221,248 @@ public class PlatformLogger {
* (i.e. its level is OFF). * (i.e. its level is OFF).
*/ */
public boolean isEnabled() { public boolean isEnabled() {
return logger.isEnabled(); return loggerProxy.isEnabled();
} }
/** /**
* Gets the name for this platform logger. * Gets the name for this platform logger.
*/ */
public String getName() { public String getName() {
return logger.name; return loggerProxy.name;
} }
/** /**
* Returns true if a message of the given level would actually * Returns true if a message of the given level would actually
* be logged by this logger. * be logged by this logger.
*/ */
public boolean isLoggable(int level) { public boolean isLoggable(Level level) {
return logger.isLoggable(level); // performance-sensitive method: use two monomorphic call-sites
JavaLoggerProxy jlp = javaLoggerProxy;
return jlp != null ? jlp.isLoggable(level) : loggerProxy.isLoggable(level);
} }
/** /**
* Gets the current log level. Returns 0 if the current effective level * Get the log level that has been specified for this PlatformLogger.
* is not set (equivalent to Logger.getLevel() returns null). * The result may be null, which means that this logger's
* effective level will be inherited from its parent.
*
* This method is primarily for testing purpose and not recommended
* to be used at runtime since it does not support custom j.u.l.Level.
*
* @return this PlatformLogger's level
*
* @throw IllegalArgumentException if j.u.l.Logger is set to
* a custom j.u.l.Level when java.util.logging facility is enabled
*/ */
public int getLevel() { public Level getLevel() {
return logger.getLevel(); return loggerProxy.getLevel();
} }
/** /**
* Sets the log level. * Set the log level specifying which message levels will be
* logged by this logger. Message levels lower than this
* value will be discarded. The level value {@link #OFF}
* can be used to turn off logging.
* <p>
* If the new level is null, it means that this node should
* inherit its level from its nearest ancestor with a specific
* (non-null) level value.
*
* @param newLevel the new value for the log level (may be null)
*/ */
public void setLevel(int newLevel) { public void setLevel(Level newLevel) {
logger.setLevel(newLevel); loggerProxy.setLevel(newLevel);
} }
/** /**
* Logs a SEVERE message. * Logs a SEVERE message.
*/ */
public void severe(String msg) { public void severe(String msg) {
logger.doLog(SEVERE, msg); loggerProxy.doLog(SEVERE, msg);
} }
public void severe(String msg, Throwable t) { public void severe(String msg, Throwable t) {
logger.doLog(SEVERE, msg, t); loggerProxy.doLog(SEVERE, msg, t);
} }
public void severe(String msg, Object... params) { public void severe(String msg, Object... params) {
logger.doLog(SEVERE, msg, params); loggerProxy.doLog(SEVERE, msg, params);
} }
/** /**
* Logs a WARNING message. * Logs a WARNING message.
*/ */
public void warning(String msg) { public void warning(String msg) {
logger.doLog(WARNING, msg); loggerProxy.doLog(WARNING, msg);
} }
public void warning(String msg, Throwable t) { public void warning(String msg, Throwable t) {
logger.doLog(WARNING, msg, t); loggerProxy.doLog(WARNING, msg, t);
} }
public void warning(String msg, Object... params) { public void warning(String msg, Object... params) {
logger.doLog(WARNING, msg, params); loggerProxy.doLog(WARNING, msg, params);
} }
/** /**
* Logs an INFO message. * Logs an INFO message.
*/ */
public void info(String msg) { public void info(String msg) {
logger.doLog(INFO, msg); loggerProxy.doLog(INFO, msg);
} }
public void info(String msg, Throwable t) { public void info(String msg, Throwable t) {
logger.doLog(INFO, msg, t); loggerProxy.doLog(INFO, msg, t);
} }
public void info(String msg, Object... params) { public void info(String msg, Object... params) {
logger.doLog(INFO, msg, params); loggerProxy.doLog(INFO, msg, params);
} }
/** /**
* Logs a CONFIG message. * Logs a CONFIG message.
*/ */
public void config(String msg) { public void config(String msg) {
logger.doLog(CONFIG, msg); loggerProxy.doLog(CONFIG, msg);
} }
public void config(String msg, Throwable t) { public void config(String msg, Throwable t) {
logger.doLog(CONFIG, msg, t); loggerProxy.doLog(CONFIG, msg, t);
} }
public void config(String msg, Object... params) { public void config(String msg, Object... params) {
logger.doLog(CONFIG, msg, params); loggerProxy.doLog(CONFIG, msg, params);
} }
/** /**
* Logs a FINE message. * Logs a FINE message.
*/ */
public void fine(String msg) { public void fine(String msg) {
logger.doLog(FINE, msg); loggerProxy.doLog(FINE, msg);
} }
public void fine(String msg, Throwable t) { public void fine(String msg, Throwable t) {
logger.doLog(FINE, msg, t); loggerProxy.doLog(FINE, msg, t);
} }
public void fine(String msg, Object... params) { public void fine(String msg, Object... params) {
logger.doLog(FINE, msg, params); loggerProxy.doLog(FINE, msg, params);
} }
/** /**
* Logs a FINER message. * Logs a FINER message.
*/ */
public void finer(String msg) { public void finer(String msg) {
logger.doLog(FINER, msg); loggerProxy.doLog(FINER, msg);
} }
public void finer(String msg, Throwable t) { public void finer(String msg, Throwable t) {
logger.doLog(FINER, msg, t); loggerProxy.doLog(FINER, msg, t);
} }
public void finer(String msg, Object... params) { public void finer(String msg, Object... params) {
logger.doLog(FINER, msg, params); loggerProxy.doLog(FINER, msg, params);
} }
/** /**
* Logs a FINEST message. * Logs a FINEST message.
*/ */
public void finest(String msg) { public void finest(String msg) {
logger.doLog(FINEST, msg); loggerProxy.doLog(FINEST, msg);
} }
public void finest(String msg, Throwable t) { public void finest(String msg, Throwable t) {
logger.doLog(FINEST, msg, t); loggerProxy.doLog(FINEST, msg, t);
} }
public void finest(String msg, Object... params) { public void finest(String msg, Object... params) {
logger.doLog(FINEST, msg, params); loggerProxy.doLog(FINEST, msg, params);
} }
/** /**
* Default platform logging support - output messages to * Abstract base class for logging support, defining the API and common field.
* System.err - equivalent to ConsoleHandler with SimpleFormatter.
*/ */
static class LoggerProxy { private static abstract class LoggerProxy {
private static final PrintStream defaultStream = System.err;
final String name; final String name;
volatile int levelValue;
volatile int effectiveLevel = 0; // current effective level value
LoggerProxy(String name) { protected LoggerProxy(String name) {
this(name, defaultLevel); this.name = name;
} }
LoggerProxy(String name, int level) { abstract boolean isEnabled();
this.name = name;
this.levelValue = level == 0 ? defaultLevel : level; abstract Level getLevel();
abstract void setLevel(Level newLevel);
abstract void doLog(Level level, String msg);
abstract void doLog(Level level, String msg, Throwable thrown);
abstract void doLog(Level level, String msg, Object... params);
abstract boolean isLoggable(Level level);
}
private static final class DefaultLoggerProxy extends LoggerProxy {
/**
* Default platform logging support - output messages to System.err -
* equivalent to ConsoleHandler with SimpleFormatter.
*/
private static PrintStream outputStream() {
return System.err;
} }
boolean isEnabled() { volatile Level effectiveLevel; // effective level (never null)
return levelValue != OFF; volatile Level level; // current level set for this node (may be null)
DefaultLoggerProxy(String name) {
super(name);
this.effectiveLevel = deriveEffectiveLevel(null);
this.level = null;
} }
int getLevel() { boolean isEnabled() {
return effectiveLevel; return effectiveLevel != OFF;
} }
void setLevel(int newLevel) { Level getLevel() {
levelValue = newLevel; return level;
effectiveLevel = newLevel;
} }
void doLog(int level, String msg) { void setLevel(Level newLevel) {
if (level < levelValue || levelValue == OFF) { Level oldLevel = level;
return; if (oldLevel != newLevel) {
level = newLevel;
effectiveLevel = deriveEffectiveLevel(newLevel);
} }
defaultStream.print(format(level, msg, null));
} }
void doLog(int level, String msg, Throwable thrown) { void doLog(Level level, String msg) {
if (level < levelValue || levelValue == OFF) { if (isLoggable(level)) {
return; outputStream().print(format(level, msg, null));
} }
defaultStream.print(format(level, msg, thrown));
} }
void doLog(int level, String msg, Object... params) { void doLog(Level level, String msg, Throwable thrown) {
if (level < levelValue || levelValue == OFF) { if (isLoggable(level)) {
return; outputStream().print(format(level, msg, thrown));
} }
String newMsg = formatMessage(msg, params);
defaultStream.print(format(level, newMsg, null));
} }
public boolean isLoggable(int level) { void doLog(Level level, String msg, Object... params) {
if (level < levelValue || levelValue == OFF) { if (isLoggable(level)) {
return false; String newMsg = formatMessage(msg, params);
outputStream().print(format(level, newMsg, null));
} }
return true; }
boolean isLoggable(Level level) {
Level effectiveLevel = this.effectiveLevel;
return level.intValue() >= effectiveLevel.intValue() && effectiveLevel != OFF;
}
// derive effective level (could do inheritance search like j.u.l.Logger)
private Level deriveEffectiveLevel(Level level) {
return level == null ? DEFAULT_LEVEL : level;
} }
// Copied from java.util.logging.Formatter.formatMessage // Copied from java.util.logging.Formatter.formatMessage
...@@ -401,7 +494,7 @@ public class PlatformLogger { ...@@ -401,7 +494,7 @@ public class PlatformLogger {
// minimize memory allocation // minimize memory allocation
private Date date = new Date(); private Date date = new Date();
private synchronized String format(int level, String msg, Throwable thrown) { private synchronized String format(Level level, String msg, Throwable thrown) {
date.setTime(System.currentTimeMillis()); date.setTime(System.currentTimeMillis());
String throwable = ""; String throwable = "";
if (thrown != null) { if (thrown != null) {
...@@ -417,7 +510,7 @@ public class PlatformLogger { ...@@ -417,7 +510,7 @@ public class PlatformLogger {
date, date,
getCallerInfo(), getCallerInfo(),
name, name,
PlatformLogger.getLevelName(level), level.name(),
msg, msg,
throwable); throwable);
} }
...@@ -464,58 +557,41 @@ public class PlatformLogger { ...@@ -464,58 +557,41 @@ public class PlatformLogger {
} }
/** /**
* JavaLogger forwards all the calls to its corresponding * JavaLoggerProxy forwards all the calls to its corresponding
* java.util.logging.Logger object. * java.util.logging.Logger object.
*/ */
static class JavaLogger extends LoggerProxy { private static final class JavaLoggerProxy extends LoggerProxy {
private static final Map<Integer, Object> levelObjects = // initialize javaLevel fields for mapping from Level enum -> j.u.l.Level object
new HashMap<>();
static { static {
if (LoggingSupport.isAvailable()) { for (Level level : Level.values()) {
// initialize the map to Level objects level.javaLevel = LoggingSupport.parseLevel(level.name());
getLevelObjects();
} }
} }
private static void getLevelObjects() { private final /* java.util.logging.Logger */ Object javaLogger;
// get all java.util.logging.Level objects
int[] levelArray = new int[] {OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL};
for (int l : levelArray) {
Object level = LoggingSupport.parseLevel(getLevelName(l));
levelObjects.put(l, level);
}
}
private final Object javaLogger; JavaLoggerProxy(String name) {
JavaLogger(String name) { this(name, null);
this(name, 0);
} }
JavaLogger(String name, int level) { JavaLoggerProxy(String name, Level level) {
super(name, level); super(name);
this.javaLogger = LoggingSupport.getLogger(name); this.javaLogger = LoggingSupport.getLogger(name);
if (level != 0) { if (level != null) {
// level has been updated and so set the Logger's level // level has been updated and so set the Logger's level
LoggingSupport.setLevel(javaLogger, levelObjects.get(level)); LoggingSupport.setLevel(javaLogger, level.javaLevel);
} }
} }
/** void doLog(Level level, String msg) {
* Let Logger.log() do the filtering since if the level of a LoggingSupport.log(javaLogger, level.javaLevel, msg);
* platform logger is altered directly from
* java.util.logging.Logger.setLevel(), the levelValue will
* not be updated.
*/
void doLog(int level, String msg) {
LoggingSupport.log(javaLogger, levelObjects.get(level), msg);
} }
void doLog(int level, String msg, Throwable t) { void doLog(Level level, String msg, Throwable t) {
LoggingSupport.log(javaLogger, levelObjects.get(level), msg, t); LoggingSupport.log(javaLogger, level.javaLevel, msg, t);
} }
void doLog(int level, String msg, Object... params) { void doLog(Level level, String msg, Object... params) {
if (!isLoggable(level)) { if (!isLoggable(level)) {
return; return;
} }
...@@ -526,49 +602,32 @@ public class PlatformLogger { ...@@ -526,49 +602,32 @@ public class PlatformLogger {
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
sparams [i] = String.valueOf(params[i]); sparams [i] = String.valueOf(params[i]);
} }
LoggingSupport.log(javaLogger, levelObjects.get(level), msg, sparams); LoggingSupport.log(javaLogger, level.javaLevel, msg, sparams);
} }
boolean isEnabled() { boolean isEnabled() {
Object level = LoggingSupport.getLevel(javaLogger); return LoggingSupport.isLoggable(javaLogger, Level.OFF.javaLevel);
return level == null || level.equals(levelObjects.get(OFF)) == false;
} }
int getLevel() { /**
Object level = LoggingSupport.getLevel(javaLogger); * Returns the PlatformLogger.Level mapped from j.u.l.Level
if (level != null) { * set in the logger.
for (Map.Entry<Integer, Object> l : levelObjects.entrySet()) { * @throw IllegalArgumentException if j.u.l.Logger is set to
if (level == l.getValue()) { * a custom j.u.l.Level
return l.getKey(); */
} Level getLevel() {
} Object javaLevel = LoggingSupport.getLevel(javaLogger);
} return javaLevel == null
return 0; ? null
: Level.valueOf(LoggingSupport.getLevelName(javaLevel));
} }
void setLevel(int newLevel) { void setLevel(Level level) {
levelValue = newLevel; LoggingSupport.setLevel(javaLogger, level == null ? null : level.javaLevel);
LoggingSupport.setLevel(javaLogger, levelObjects.get(newLevel));
} }
public boolean isLoggable(int level) { boolean isLoggable(Level level) {
return LoggingSupport.isLoggable(javaLogger, levelObjects.get(level)); return LoggingSupport.isLoggable(javaLogger, level.javaLevel);
} }
} }
private static String getLevelName(int level) {
switch (level) {
case OFF : return "OFF";
case SEVERE : return "SEVERE";
case WARNING : return "WARNING";
case INFO : return "INFO";
case CONFIG : return "CONFIG";
case FINE : return "FINE";
case FINER : return "FINER";
case FINEST : return "FINEST";
case ALL : return "ALL";
default : return "UNKNOWN";
}
}
} }
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 6882376 6985460 * @bug 6882376 6985460 8010309
* @summary Test if java.util.logging.Logger is created before and after * @summary Test if java.util.logging.Logger is created before and after
* logging is enabled. Also validate some basic PlatformLogger * logging is enabled. Also validate some basic PlatformLogger
* operations. othervm mode to make sure java.util.logging * operations. othervm mode to make sure java.util.logging
...@@ -33,11 +33,11 @@ ...@@ -33,11 +33,11 @@
* @run main/othervm PlatformLoggerTest * @run main/othervm PlatformLoggerTest
*/ */
import java.lang.reflect.Field;
import java.util.logging.*; import java.util.logging.*;
import sun.util.logging.PlatformLogger; import sun.util.logging.PlatformLogger;
public class PlatformLoggerTest { public class PlatformLoggerTest {
private static final int defaultEffectiveLevel = 0;
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
final String FOO_PLATFORM_LOGGER = "test.platformlogger.foo"; final String FOO_PLATFORM_LOGGER = "test.platformlogger.foo";
final String BAR_PLATFORM_LOGGER = "test.platformlogger.bar"; final String BAR_PLATFORM_LOGGER = "test.platformlogger.bar";
...@@ -72,6 +72,7 @@ public class PlatformLoggerTest { ...@@ -72,6 +72,7 @@ public class PlatformLoggerTest {
foo.setLevel(PlatformLogger.SEVERE); foo.setLevel(PlatformLogger.SEVERE);
checkLogger(FOO_PLATFORM_LOGGER, Level.SEVERE); checkLogger(FOO_PLATFORM_LOGGER, Level.SEVERE);
checkPlatformLoggerLevels(foo, bar);
} }
private static void checkPlatformLogger(PlatformLogger logger, String name) { private static void checkPlatformLogger(PlatformLogger logger, String name) {
...@@ -80,9 +81,9 @@ public class PlatformLoggerTest { ...@@ -80,9 +81,9 @@ public class PlatformLoggerTest {
logger.getName() + " but expected " + name); logger.getName() + " but expected " + name);
} }
if (logger.getLevel() != defaultEffectiveLevel) { if (logger.getLevel() != null) {
throw new RuntimeException("Invalid default level for logger " + throw new RuntimeException("Invalid default level for logger " +
logger.getName()); logger.getName() + ": " + logger.getLevel());
} }
if (logger.isLoggable(PlatformLogger.FINE) != false) { if (logger.isLoggable(PlatformLogger.FINE) != false) {
...@@ -91,7 +92,7 @@ public class PlatformLoggerTest { ...@@ -91,7 +92,7 @@ public class PlatformLoggerTest {
} }
logger.setLevel(PlatformLogger.FINER); logger.setLevel(PlatformLogger.FINER);
if (logger.getLevel() != Level.FINER.intValue()) { if (logger.getLevel() != PlatformLogger.FINER) {
throw new RuntimeException("Invalid level for logger " + throw new RuntimeException("Invalid level for logger " +
logger.getName() + " " + logger.getLevel()); logger.getName() + " " + logger.getLevel());
} }
...@@ -125,6 +126,73 @@ public class PlatformLoggerTest { ...@@ -125,6 +126,73 @@ public class PlatformLoggerTest {
logger.info("Test info(String)"); logger.info("Test info(String)");
} }
private static void checkPlatformLoggerLevels(PlatformLogger... loggers) {
final Level[] levels = new Level[] {
Level.ALL, Level.CONFIG, Level.FINE, Level.FINER, Level.FINEST,
Level.INFO, Level.OFF, Level.SEVERE, Level.WARNING
};
int count = PlatformLogger.Level.values().length;
if (levels.length != count) {
throw new RuntimeException("There are " + count +
" PlatformLogger.Level members, but " + levels.length +
" standard java.util.logging levels - the numbers should be equal.");
}
// check mappings
for (Level level : levels) {
checkPlatformLoggerLevelMapping(level);
}
for (Level level : levels) {
PlatformLogger.Level platformLevel = PlatformLogger.Level.valueOf(level.getName());
for (PlatformLogger logger : loggers) {
// verify PlatformLogger.setLevel to a given level
logger.setLevel(platformLevel);
PlatformLogger.Level retrievedPlatformLevel = logger.getLevel();
if (platformLevel != retrievedPlatformLevel) {
throw new RuntimeException("Retrieved PlatformLogger level " +
retrievedPlatformLevel +
" is not the same as set level " + platformLevel);
}
// check the level set in java.util.logging.Logger
Logger javaLogger = LogManager.getLogManager().getLogger(logger.getName());
Level javaLevel = javaLogger.getLevel();
if (javaLogger.getLevel() != level) {
throw new RuntimeException("Retrieved backing java.util.logging.Logger level " +
javaLevel + " is not the expected " + level);
}
}
}
}
private static void checkPlatformLoggerLevelMapping(Level level) {
// map the given level to PlatformLogger.Level of the same name and value
PlatformLogger.Level platformLevel = PlatformLogger.Level.valueOf(level.getName());
if (platformLevel.intValue() != level.intValue()) {
throw new RuntimeException("Mismatched level: " + level
+ " PlatformLogger.Level" + platformLevel);
}
PlatformLogger.Level plevel;
try {
// validate if there is a public static final field in PlatformLogger
// matching the level name
Field platformLevelField = PlatformLogger.class.getField(level.getName());
plevel = (PlatformLogger.Level) platformLevelField.get(null);
} catch (Exception e) {
throw new RuntimeException("No public static PlatformLogger." + level.getName() +
" field", e);
}
if (!plevel.name().equals(level.getName()))
throw new RuntimeException("The value of PlatformLogger." + level.getName() + ".name() is "
+ platformLevel.name() + " but expected " + level.getName());
if (plevel.intValue() != level.intValue())
throw new RuntimeException("The value of PlatformLogger." + level.intValue() + ".intValue() is "
+ platformLevel.intValue() + " but expected " + level.intValue());
}
static Point[] getPoints() { static Point[] getPoints() {
Point[] res = new Point[3]; Point[] res = new Point[3];
res[0] = new Point(0,0); res[0] = new Point(0,0);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册