8010309 : PlatformLogger: isLoggable performance / waste due to HashMap<Integer, Level> leads to Integer allocations (boxing)
Peter Levart
peter.levart at gmail.com
Thu Mar 21 19:31:45 UTC 2013
On 03/21/2013 07:25 PM, Laurent Bourgès wrote:
> Peter,
>
> My last idea for today:
> Consider the object field of the LevelEnum as a mutable field (non
> final), JavaLogger initialization can then set its value during its
> initialization (j.u.l available).
>
> Doing so, it will avoid any Map.get() in isLoggable(int) to improve
> performance as done in my patch.
Good idea. And it's thread-safe too I think, since the static
initializer HB any instance methods can run and the field is only
accessed from JavaLogger's instance methods....
Here's the new rev:
http://dl.dropbox.com/u/101777488/jdk8-tl/PlatformLogger/webrev.05/index.html
I removed the object() and forObject() methods and access the field
directly. I also renamed it to something more significant. forObject()
is not necessary, since it only had one call site and I just inlined it.
I also "took the opportunity". Now we're back to original + 9 LOC ...
Regards, Peter
>
> I will test this solution soon...
>
> My previous message I forgot to send to the mailing list:
>
> my last two cents:
> - I prefer having theobject()and forObject() methods in the
> JavaLogger class because it reduces the risk to use it elsewhere and
> it avoids double indirection: JavaLogger calls these methods that call
> back JavaLogger to access its fields ... too obfuscated for me
> +
> + // the following two methods are (and should only be) called from JavaLogger...
> +
> + Object object() {
>
> + return JavaLogger.levelObjects.get(this);
> + }
> +
> + static LevelEnum forObject(Object levelObject) {
>
> + LevelEnum levelEnum = JavaLogger.levelEnums.get(levelObject);
> + return levelEnum == null ? UNKNOWN : levelEnum;
> + }
>
> + }
> - take the opportunity to replace repeated lines in LoggerProxy.doLog() methods by isLoggable(level):
> if (level < levelValue || levelValue == OFF) {
>
>
> return;
> }
> Great job anyway,
> Cheers,
> Laurent
>
>
>
> 2013/3/21 Peter Levart <peter.levart at gmail.com
> <mailto:peter.levart at gmail.com>>
>
> Hi Laurent, Mandy,
>
> I think I've got it now. It's a middle-ground. It would be a shame
> to loose the code-reuse (one switch instead of two). So I only
> moved the levelObjects to JavaLogger, not the entire LevelEnum:
>
> http://dl.dropbox.com/u/101777488/jdk8-tl/PlatformLogger/webrev.04/index.html
>
> So this is basically similar to original code. It just uses
> LevelEnum instead of java.lang.Integer and EnumMap instead of
> HashMap. Hopefully these perform better. If I moved the LevelEnum
> into the JavaLogger, I would have to re-instate the second switch
> for LoggerProxy and the solution would not be much simpler than
> your patch, Laurent. This is still just 20 LOC more than original
> code.
>
> Regards, Peter
>
>
> On 03/21/2013 05:09 PM, Peter Levart wrote:
>> You're right, loggingEnabled can change afterwards. I'll correct
>> the code as suggested...
>>
>> Peter
>>
>> On 03/21/2013 04:57 PM, Laurent Bourgès wrote:
>>> Peter,
>>>
>>> I am convinced it is better if the LevelEnum belongs to
>>> JavaLogger class (encapsulated so defered initialization).
>>>
>>> Here is a typical scenario:
>>> 1 - PlatformLogger initialized (not JUL) => LoggerProxy must
>>> work so LevelEnum can not be used and the formergetLevelName()
>>> (switch case) is required.
>>> 2 - JUL initialized: calls redirectPlatformLogger() =>
>>> JavaLoggers created => LevelEnum initialized (Level object can
>>> be retrieved from LoggingSupport)
>>>
>>> For example, JUL can be started programmatically so the
>>> loggingEnabled flag is not enough to initialize the
>>> LevelEnum.object at step 1 and it will be null. Then at step 2,
>>> LevelEnum.object are null so the JavaLogger is broken.
>>>
>>> Here is a test of this scenario:
>>> public static void main(String[] args) {
>>>
>>> final PlatformLogger log =
>>> PlatformLogger.getLogger("sun.awt.X11"); // 1: LoggerProxy
>>>
>>> if (log.isLoggable(PlatformLogger.INFO)) {
>>> log.info <http://log.info>("PlatformLogger.INFO: LoggerProxy");
>>> }
>>>
>>> final Logger logger = Logger.getLogger("test");
>>> // calls PlatformLogger.redirectPlatformLoggers(); // 2 :
>>> JavaLogger
>>>
>>> if (log.isLoggable(PlatformLogger.INFO)) {
>>> log.info <http://log.info>("PlatformLogger.INFO: JavaLogger");
>>> }
>>>
>>> logger.info <http://logger.info>("done");
>>> }
>>>
>>> Laurent
>>>
>>> 2013/3/21 Peter Levart <peter.levart at gmail.com
>>> <mailto:peter.levart at gmail.com>>
>>>
>>> Hi Laurent, Mandy,
>>>
>>> Let me try one more time (it would be less optimal to have 2
>>> switch statements instead of one). Here's the 3rd webrev:
>>>
>>> http://dl.dropbox.com/u/101777488/jdk8-tl/PlatformLogger/webrev.03/index.html
>>>
>>> The changes:
>>> - added the comments
>>> - made LevelEnum private (to not be tempted to be used from
>>> outside the PlatformLogger)
>>> - used the loggingEnabled flag as a pre-check when trying to
>>> parse the level objects
>>>
>>>
>>> What do you think?
>>>
>>> Regards, Peter
>>>
>>> On 03/21/2013 04:06 PM, Laurent Bourgès wrote:
>>>> Thanks Mandy for the clarifications !
>>>>
>>>> Peter, I propose to:
>>>> - move the LevelEnum into the JavaLogger class in order to
>>>> initialize it as later as possible i.e. after j.u.l calls
>>>> redirectPlatformLoggers()
>>>> - only use it in JavaLogger class (private enum) so revert
>>>> changes to PlatformLogger and LoggerProxy classes
>>>> - add few comments in the code to explain lazy
>>>> initialization (see mandy's answer)
>>>>
>>>> Finally, could you keep my comment before the switch case
>>>> (high occurences first) ?
>>>> + static LevelEnum forValue(int levelValue) {
>>>>
>>>> + // higher occurences first (finest, fine, finer, info)
>>>> + // based on isLoggable(level) calls (03/20/2013)
>>>> + // in jdk project only (including generated sources)
>>>>
>>>> + switch (levelValue) {
>>>> + case PlatformLogger.FINEST: return FINEST; // 116 + 2257 matches in generated files
>>>> + case PlatformLogger.FINE: return FINE; // 270
>>>>
>>>> + case PlatformLogger.FINER: return FINER; // 157
>>>> + case PlatformLogger.INFO: return INFO; // 39
>>>> + case PlatformLogger.WARNING: return WARNING; // 12
>>>>
>>>> + case PlatformLogger.CONFIG: return CONFIG; // 6
>>>> + case PlatformLogger.SEVERE: return SEVERE; // 1
>>>> + case PlatformLogger.OFF: return OFF; // 0
>>>>
>>>> + case PlatformLogger.ALL: return ALL; // 0
>>>> + default: return UNKNOWN;
>>>> + }
>>>>
>>>> + }
>>>>
>>>> cheers,
>>>> Laurent
>>>>
>>>> 2013/3/21 Mandy Chung <mandy.chung at oracle.com
>>>> <mailto:mandy.chung at oracle.com>>
>>>>
>>>> Laurent, Peter,
>>>>
>>>> I haven't looked at the patch yet. One thing worths
>>>> mentioning is that PlatformLogger was added for the
>>>> platform code to use so as to avoid the initialization
>>>> of java.util.logging since logging is not turned on by
>>>> default and that to reduce the startup overhead. In
>>>> addition, it also enables the elimination of the core
>>>> classes dependency from java.util.logging for
>>>> modularization effort. Therefore the PlatformLogger
>>>> only lazily looks up the Level object when
>>>> java.util.logging is present and also has been
>>>> initialized by application code.
>>>>
>>>> Mandy
>>>>
>>>>
>>>> On 3/21/2013 7:45 AM, Peter Levart wrote:
>>>>> On 03/21/2013 03:30 PM, Laurent Bourgès wrote:
>>>>>> Peter,
>>>>>>
>>>>>> your solution looks better; I wanted my patch to be
>>>>>> simple, efficient and only modify the JavaLogger
>>>>>> class (localized changes).
>>>>>>
>>>>>> In your patch, I have doubts related to lazy and
>>>>>> conditional initialization in JavaLogger (static
>>>>>> initialization):
>>>>>> if (LoggingSupport.isAvailable()) {
>>>>>> // initialize ...
>>>>>> }
>>>>>
>>>>> In original code, if LoggingSupport.isAvailable()
>>>>> returned false, levelObjects map remained empty and
>>>>> consequently null was used as the level object passed
>>>>> to LoggingSupport methods. In LevelEnum I try to keep
>>>>> this logic. When LevelEnum is first used, it's
>>>>> constants are initialized and level objects with them. If
>>>>> LoggingSupport.isAvailable() returns false, level
>>>>> objects are initialized to null.
>>>>>
>>>>> I just noticed there's a bug in initialization of the
>>>>> LevelEnum.UNKNOWN member constant. It should not try
>>>>> to parse level object. Here's an update:
>>>>>
>>>>> http://dl.dropbox.com/u/101777488/jdk8-tl/PlatformLogger/webrev.02/index.html
>>>>>
>>>>> But your concern might be correct. In my code
>>>>> LevelEnum is also used from the LoggerProxy.format()
>>>>> method (in addition to all the places in JavaLogger)
>>>>> to obtain the level name for formatting. If this
>>>>> method is called the first time while
>>>>> LoggingSupport.isAvailable() returns false and that
>>>>> happens before JavaLogger uses LevelEnum for the first
>>>>> time (and at that time LoggingSupport.isAvailable()
>>>>> would return true), then level objects will not be
>>>>> initialized correctly.
>>>>>
>>>>> Lazy initialization of level objects might help (for
>>>>> the price of added complexity)...
>>>>>
>>>>> Regards, Peter
>>>>>
>>>>>> Does somebody have the knowledge about LoggingSupport.isAvailable()
>>>>>>
>>>>>> and the lazy PlatformLogger initialization (JavaLogger are only used when j.u.l is initialized) ?
>>>>>>
>>>>>>
>>>>>> What's happening if LoggingSupport.isAvailable() returns false in your patch ?
>>>>>> - LevelEnum instances are incorrectly initialized:object field is null !
>>>>>>
>>>>>> - PlatformLogger is then broken ... as Level object are required by j.u.l calls
>>>>>>
>>>>>>
>>>>>> To fix both problems, moving theLevelEnum into JavaLogger should help and check nulls onLevelEnum.object field.
>>>>>>
>>>>>>
>>>>>> Thanks for your feedback,
>>>>>> Laurent
>>>>>>
>>>>>>
>>>>>> 2013/3/21 Peter Levart <peter.levart at gmail.com
>>>>>> <mailto:peter.levart at gmail.com>>
>>>>>>
>>>>>> On 03/21/2013 12:12 PM, Laurent Bourgès wrote:
>>>>>>
>>>>>> Here is an improved patch tested on JDK7u13
>>>>>> and JDK8 internal build on my
>>>>>> machine linux x64:
>>>>>> http://jmmc.fr/~bourgesl/share/webrev-8010309/ <http://jmmc.fr/%7Ebourgesl/share/webrev-8010309/>
>>>>>>
>>>>>> FYI, I removed completely the Map<Integer,
>>>>>> Object> levelObjects and used
>>>>>> two arrays to perform the PlatformLogger's
>>>>>> level (int) to j.u.l.Level
>>>>>> mapping:
>>>>>>
>>>>>> I decided to keep it simple as possible (no
>>>>>> enum ...) and used a switch
>>>>>> case based on current level occurences:
>>>>>>
>>>>>>
>>>>>> Hi Laurent,
>>>>>>
>>>>>> In my experience enums are just the right and
>>>>>> most compact tool for coding such constant
>>>>>> associations. Here's a quick try (ripping off
>>>>>> your optimized switch ;-):
>>>>>>
>>>>>> http://dl.dropbox.com/u/101777488/jdk8-tl/PlatformLogger/webrev.01/index.html
>>>>>>
>>>>>> ...it adds 12 LOC to the original PlatformLogger
>>>>>> and is 43 LOC less tha your patch. In addition:
>>>>>>
>>>>>> - only one switch instead of two (to maintain)
>>>>>> - no parallel IDX_ constants
>>>>>>
>>>>>> What do you think?
>>>>>>
>>>>>> Regards, Peter
>>>>>>
>>>>>>
>>>>>>
>>>>>> 510 /**
>>>>>> 511 * Return the corresponding
>>>>>> j.u.l.Level instance
>>>>>> 512 * @param level PlatformLogger
>>>>>> level as integer
>>>>>> 513 * @return Object (j.u.l.Level
>>>>>> instance) or null if no
>>>>>> matching level
>>>>>> 514 */
>>>>>> 515 private static Object getLevel(final
>>>>>> int level) {
>>>>>> 516 if (levelObjects == null) {
>>>>>> 517 return null;
>>>>>> 518 }
>>>>>> 519 // higher occurences first (finest,
>>>>>> fine, finer, info)
>>>>>> 520 // based on isLoggable(level) calls
>>>>>> (03/20/2013)
>>>>>> 521 // in jdk project only (including
>>>>>> generated sources)
>>>>>> 522 switch (level) {
>>>>>> 523 case FINEST : return
>>>>>> levelObjects[IDX_FINEST];
>>>>>> // 116 + 2257 matches in generated files
>>>>>> 524 case FINE : return
>>>>>> levelObjects[IDX_FINE]; // 270
>>>>>> 525 case FINER : return
>>>>>> levelObjects[IDX_FINER]; // 157
>>>>>> 526 case INFO : return
>>>>>> levelObjects[IDX_INFO]; // 39
>>>>>> 527 case WARNING : return
>>>>>> levelObjects[IDX_WARNING]; // 12
>>>>>> 528 case CONFIG : return
>>>>>> levelObjects[IDX_CONFIG]; // 6
>>>>>> 529 case SEVERE : return
>>>>>> levelObjects[IDX_SEVERE]; // 1
>>>>>> 530 case OFF : return
>>>>>> levelObjects[IDX_OFF]; // 0
>>>>>> 531 case ALL : return
>>>>>> levelObjects[IDX_ALL]; // 0
>>>>>> 532 default : return null;
>>>>>> 533 }
>>>>>> 534 }
>>>>>>
>>>>>> I enhanced the PlatformLoggerTest class also
>>>>>> and figured out that TLAB
>>>>>> optimized Integer allocations but I think the
>>>>>> patch is still useful.
>>>>>>
>>>>>> Can you have a look to the patch ?
>>>>>> Should I write a jtreg test (performance /
>>>>>> GC issue) ?
>>>>>>
>>>>>> Cheers,
>>>>>> Laurent
>>>>>>
>>>>>>
>>>>>> 2013/3/20 Mandy Chung <mandy.chung at oracle.com
>>>>>> <mailto:mandy.chung at oracle.com>>
>>>>>>
>>>>>> Hi Laurent,
>>>>>>
>>>>>> Thank you for signing the OCA. Your
>>>>>> contribution is very welcome. You
>>>>>> can submit a patch for this bug (see [1])
>>>>>> to Core libraries group which
>>>>>> owns logging. Jim Gish and I will
>>>>>> sponsor it.
>>>>>>
>>>>>> Thanks
>>>>>> Mandy
>>>>>> [1] http://openjdk.java.net/contribute/
>>>>>>
>>>>>>
>>>>>> On 3/20/2013 5:45 AM, Laurent Bourgès wrote:
>>>>>>
>>>>>> Hi mandy,
>>>>>>
>>>>>> Do you want me to propose an improved
>>>>>> patch to remove the former Map and
>>>>>> fix the getLevel() method ? or you prefer
>>>>>> fix on your own ?
>>>>>>
>>>>>> Is it better to discuss the fix on the
>>>>>> bug database (still not visible) ?
>>>>>>
>>>>>> Laurent
>>>>>>
>>>>>> 2013/3/19 Mandy Chung
>>>>>> <mandy.chung at oracle.com
>>>>>> <mailto:mandy.chung at oracle.com>>
>>>>>>
>>>>>> Hi Laurent,
>>>>>>
>>>>>> Thanks for the contribution. I agree
>>>>>> that the map can be replaced with a
>>>>>> direct mapping from a int value to
>>>>>> Level object and avoid the autoboxing
>>>>>> conversion.
>>>>>>
>>>>>> I have filed a bug to track this and
>>>>>> target this for JDK8:
>>>>>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=
>>>>>> 8010309
>>>>>>
>>>>>> Thanks
>>>>>> Mandy
>>>>>>
>>>>>>
>>>>>> On 3/19/13 5:19 AM, Laurent Bourgès
>>>>>> wrote:
>>>>>>
>>>>>> Dear all,
>>>>>>
>>>>>> I run recently netbeans profiler on
>>>>>> my swing application
>>>>>> (Aspro2:http://www.jmmc.fr/aspro
>>>>>> ) under linux x64 platform and
>>>>>> figured out a
>>>>>> performance and waste issue related
>>>>>> to PlatformLogger.
>>>>>>
>>>>>> Actually, the JavaLogger
>>>>>> implementation uses a Map<Integer,
>>>>>> Object>
>>>>>> levelObjects to store mapping between
>>>>>> PlatformLogger's levels (int) and JUL
>>>>>> Level instances.
>>>>>>
>>>>>> However, the isLoggable(int level)
>>>>>> method is highly used by awt project and
>>>>>> other JDK projects and it leads to
>>>>>> many Integer allocations as autoboxing
>>>>>> converts the level as int to an
>>>>>> Integer instance used by the
>>>>>> Map.get() call.
>>>>>>
>>>>>> /**
>>>>>> * JavaLogger forwards all the
>>>>>> calls to its corresponding
>>>>>> * java.util.logging.Logger object.
>>>>>> */
>>>>>> static class JavaLogger extends
>>>>>> LoggerProxy {
>>>>>> private static final* Map<Integer,
>>>>>> Object>* levelObjects = new
>>>>>> HashMap<>();
>>>>>> ...
>>>>>> public boolean isLoggable(*int level*) {
>>>>>> return
>>>>>> LoggingSupport.isLoggable(javaLogger, *
>>>>>> levelObjects.get(level)*);
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> I wrote a simple test to illustrate
>>>>>> that performance / waste problem:
>>>>>> PlatformLoggerTest that simply
>>>>>> performs 1 million DISABLED log
>>>>>> statements:
>>>>>> if
>>>>>> (log.isLoggable(PlatformLogger.FINEST)) {
>>>>>> log.finest("test
>>>>>> PlatformLogger.FINEST");
>>>>>> }
>>>>>>
>>>>>> As you can see in screenshots:
>>>>>> - 5 million Integer instances are
>>>>>> allocated
>>>>>> - Integer.valueOf(int) is called 5
>>>>>> million times (autoboxing)
>>>>>> - HashMap.get() represents 30% of the
>>>>>> test time
>>>>>> - patched PlatformLogger is 3x times
>>>>>> faster
>>>>>> [jvm options: -Xms8m -Xmx8m -verbose:gc]
>>>>>>
>>>>>> I suggest you to use an alternative
>>>>>> way to map PlatformLogger's levels
>>>>>> (int) and JUL Level instances to fix
>>>>>> that performance / memory issue: I
>>>>>> added the getLevel(int level) method
>>>>>> that performs a switch case to return
>>>>>> the corresponding Level object (quick
>>>>>> and dirty solution).
>>>>>>
>>>>>> I advocate this is not a very clean
>>>>>> solution but I prefer efficiency here:
>>>>>> any better solution may be
>>>>>> appropriate to avoid at least Integer
>>>>>> allocation
>>>>>> and maybe enhance performance.
>>>>>>
>>>>>> Best regards,
>>>>>> Laurent Bourgès
>>>>>>
>>>>>> PS: here is the patch as text:
>>>>>>
>>>>>> # This patch file was generated by
>>>>>> NetBeans IDE
>>>>>> # It uses platform neutral UTF-8
>>>>>> encoding and \n newlines.
>>>>>> --- PlatformLogger.java (6767)
>>>>>> +++ PlatformLogger.java (6768)
>>>>>> @@ -468,31 +468,13 @@
>>>>>> * java.util.logging.Logger object.
>>>>>> */
>>>>>> static class JavaLogger extends
>>>>>> LoggerProxy {
>>>>>> - /** Note: using Integer keys
>>>>>> leads to a lot of new Integer
>>>>>> instances !! */
>>>>>> - private static final Map<Integer,
>>>>>> Object> levelObjects = new
>>>>>> HashMap<>();
>>>>>> - /** fastest mapping to Level
>>>>>> instances from PlatformLogger level
>>>>>> as integer */
>>>>>> - private static final Object[]
>>>>>> fastLevelObjects;
>>>>>> -
>>>>>> -
>>>>>> + private static final Map<Integer,
>>>>>> Object> levelObjects =
>>>>>> + new HashMap<>();
>>>>>> +
>>>>>> static {
>>>>>> if (LoggingSupport.isAvailable()) {
>>>>>> // initialize the map to Level
>>>>>> objects
>>>>>> getLevelObjects();
>>>>>> -
>>>>>> - // initialize the fastLevelObjects:
>>>>>> - fastLevelObjects = new Object[] {
>>>>>> -
>>>>>> LoggingSupport.parseLevel(getLevelName(OFF)),
>>>>>> //
>>>>>> 0
>>>>>> -
>>>>>> LoggingSupport.parseLevel(getLevelName(SEVERE)),
>>>>>> //
>>>>>> 1
>>>>>> -
>>>>>> LoggingSupport.parseLevel(getLevelName(WARNING)),
>>>>>> //
>>>>>> 2
>>>>>> -
>>>>>> LoggingSupport.parseLevel(getLevelName(INFO)),
>>>>>> //
>>>>>> 3
>>>>>> -
>>>>>> LoggingSupport.parseLevel(getLevelName(CONFIG)),
>>>>>> //
>>>>>> 4
>>>>>> -
>>>>>> LoggingSupport.parseLevel(getLevelName(FINE)),
>>>>>> //
>>>>>> 5
>>>>>> -
>>>>>> LoggingSupport.parseLevel(getLevelName(FINER)),
>>>>>> //
>>>>>> 6
>>>>>> -
>>>>>> LoggingSupport.parseLevel(getLevelName(FINEST)),
>>>>>> //
>>>>>> 7
>>>>>> -
>>>>>> LoggingSupport.parseLevel(getLevelName(ALL))
>>>>>> //
>>>>>> 8
>>>>>> - };
>>>>>> - } else {
>>>>>> - fastLevelObjects = null; // check null
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> @@ -515,7 +497,7 @@
>>>>>> this.javaLogger =
>>>>>> LoggingSupport.getLogger(name);
>>>>>> if (level != 0) {
>>>>>> // level has been updated and so
>>>>>> set the Logger's level
>>>>>> -
>>>>>> LoggingSupport.setLevel(javaLogger,
>>>>>> getLevel(level));
>>>>>> + LoggingSupport.setLevel(javaLogger,
>>>>>> levelObjects.get(level));
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> @@ -526,11 +508,11 @@
>>>>>> * not be updated.
>>>>>> */
>>>>>> void doLog(int level,
>>>>>> String msg) {
>>>>>> - LoggingSupport.log(javaLogger,
>>>>>> getLevel(level), msg);
>>>>>> + LoggingSupport.log(javaLogger,
>>>>>> levelObjects.get(level), msg);
>>>>>> }
>>>>>>
>>>>>> void doLog(int level,
>>>>>> String msg, Throwable t) {
>>>>>> - LoggingSupport.log(javaLogger,
>>>>>> getLevel(level), msg, t);
>>>>>> + LoggingSupport.log(javaLogger,
>>>>>> levelObjects.get(level), msg,
>>>>>> t);
>>>>>> }
>>>>>>
>>>>>> void doLog(int level,
>>>>>> String msg, Object... params) {
>>>>>> @@ -544,12 +526,12 @@
>>>>>> for (int i = 0; i < len; i++) {
>>>>>> sparams [i] =
>>>>>> String.valueOf(params[i]);
>>>>>> }
>>>>>> - LoggingSupport.log(javaLogger,
>>>>>> getLevel(level), msg, sparams);
>>>>>> + LoggingSupport.log(javaLogger,
>>>>>> levelObjects.get(level), msg,
>>>>>> sparams);
>>>>>> }
>>>>>>
>>>>>> boolean isEnabled() {
>>>>>> Object level =
>>>>>> LoggingSupport.getLevel(javaLogger);
>>>>>> - return level == null ||
>>>>>> level.equals(getLevel(OFF)) == false;
>>>>>> + return level == null ||
>>>>>> level.equals(levelObjects.get(OFF)) ==
>>>>>> false;
>>>>>> }
>>>>>>
>>>>>> int getLevel() {
>>>>>> @@ -566,34 +548,12 @@
>>>>>>
>>>>>> void setLevel(int newLevel) {
>>>>>> levelValue = newLevel;
>>>>>> -
>>>>>> LoggingSupport.setLevel(javaLogger,
>>>>>> getLevel(newLevel));
>>>>>> + LoggingSupport.setLevel(javaLogger,
>>>>>> levelObjects.get(newLevel));
>>>>>> }
>>>>>>
>>>>>> public boolean isLoggable(int level) {
>>>>>> - return
>>>>>> LoggingSupport.isLoggable(javaLogger,
>>>>>> getLevel(level));
>>>>>> + return
>>>>>> LoggingSupport.isLoggable(javaLogger,
>>>>>> levelObjects.get(level));
>>>>>> }
>>>>>> -
>>>>>> - /**
>>>>>> - * Return the corresponding
>>>>>> level object (fastest implementation)
>>>>>> - * @param level
>>>>>> PlatformLogger level as primitive integer
>>>>>> - * @return Object (JUL Level
>>>>>> instance)
>>>>>> - */
>>>>>> - private static Object
>>>>>> getLevel(final int level) {
>>>>>> - // higher occurences first
>>>>>> (finest, fine, finer, info):
>>>>>> - switch (level) {
>>>>>> - case FINEST : return
>>>>>> fastLevelObjects[7];
>>>>>> - case FINE : return
>>>>>> fastLevelObjects[5];
>>>>>> - case FINER : return
>>>>>> fastLevelObjects[6];
>>>>>> - case INFO : return
>>>>>> fastLevelObjects[3];
>>>>>> - case CONFIG : return
>>>>>> fastLevelObjects[4];
>>>>>> - case WARNING : return
>>>>>> fastLevelObjects[2];
>>>>>> - case SEVERE : return
>>>>>> fastLevelObjects[1];
>>>>>> - case ALL : return
>>>>>> fastLevelObjects[8];
>>>>>> - case OFF : return
>>>>>> fastLevelObjects[0];
>>>>>> - default : return null;
>>>>>> - }
>>>>>> - }
>>>>>> -
>>>>>> }
>>>>>>
>>>>>> private static String
>>>>>> getLevelName(int level) {
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>>
>>>
>>
>
>
More information about the core-libs-dev
mailing list