Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/util/logging/PlatformLogger.java
38918 views
1
/*
2
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
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 sun.util.logging;
28
29
import java.lang.ref.WeakReference;
30
import java.io.PrintStream;
31
import java.io.PrintWriter;
32
import java.io.StringWriter;
33
import java.security.AccessController;
34
import java.security.PrivilegedAction;
35
import java.util.Arrays;
36
import java.util.Date;
37
import java.util.HashMap;
38
import java.util.Map;
39
import sun.misc.JavaLangAccess;
40
import sun.misc.SharedSecrets;
41
42
/**
43
* Platform logger provides an API for the JRE components to log
44
* messages. This enables the runtime components to eliminate the
45
* static dependency of the logging facility and also defers the
46
* java.util.logging initialization until it is enabled.
47
* In addition, the PlatformLogger API can be used if the logging
48
* module does not exist.
49
*
50
* If the logging facility is not enabled, the platform loggers
51
* will output log messages per the default logging configuration
52
* (see below). In this implementation, it does not log the
53
* the stack frame information issuing the log message.
54
*
55
* When the logging facility is enabled (at startup or runtime),
56
* the java.util.logging.Logger will be created for each platform
57
* logger and all log messages will be forwarded to the Logger
58
* to handle.
59
*
60
* Logging facility is "enabled" when one of the following
61
* conditions is met:
62
* 1) a system property "java.util.logging.config.class" or
63
* "java.util.logging.config.file" is set
64
* 2) java.util.logging.LogManager or java.util.logging.Logger
65
* is referenced that will trigger the logging initialization.
66
*
67
* Default logging configuration:
68
* global logging level = INFO
69
* handlers = java.util.logging.ConsoleHandler
70
* java.util.logging.ConsoleHandler.level = INFO
71
* java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
72
*
73
* Limitation:
74
* <JAVA_HOME>/lib/logging.properties is the system-wide logging
75
* configuration defined in the specification and read in the
76
* default case to configure any java.util.logging.Logger instances.
77
* Platform loggers will not detect if <JAVA_HOME>/lib/logging.properties
78
* is modified. In other words, unless the java.util.logging API
79
* is used at runtime or the logging system properties is set,
80
* the platform loggers will use the default setting described above.
81
* The platform loggers are designed for JDK developers use and
82
* this limitation can be workaround with setting
83
* -Djava.util.logging.config.file system property.
84
*
85
* @since 1.7
86
*/
87
public class PlatformLogger {
88
89
// The integer values must match that of {@code java.util.logging.Level}
90
// objects.
91
private static final int OFF = Integer.MAX_VALUE;
92
private static final int SEVERE = 1000;
93
private static final int WARNING = 900;
94
private static final int INFO = 800;
95
private static final int CONFIG = 700;
96
private static final int FINE = 500;
97
private static final int FINER = 400;
98
private static final int FINEST = 300;
99
private static final int ALL = Integer.MIN_VALUE;
100
101
/**
102
* PlatformLogger logging levels.
103
*/
104
public static enum Level {
105
// The name and value must match that of {@code java.util.logging.Level}s.
106
// Declare in ascending order of the given value for binary search.
107
ALL,
108
FINEST,
109
FINER,
110
FINE,
111
CONFIG,
112
INFO,
113
WARNING,
114
SEVERE,
115
OFF;
116
117
/**
118
* Associated java.util.logging.Level lazily initialized in
119
* JavaLoggerProxy's static initializer only once
120
* when java.util.logging is available and enabled.
121
* Only accessed by JavaLoggerProxy.
122
*/
123
/* java.util.logging.Level */ Object javaLevel;
124
125
// ascending order for binary search matching the list of enum constants
126
private static final int[] LEVEL_VALUES = new int[] {
127
PlatformLogger.ALL, PlatformLogger.FINEST, PlatformLogger.FINER,
128
PlatformLogger.FINE, PlatformLogger.CONFIG, PlatformLogger.INFO,
129
PlatformLogger.WARNING, PlatformLogger.SEVERE, PlatformLogger.OFF
130
};
131
132
public int intValue() {
133
return LEVEL_VALUES[this.ordinal()];
134
}
135
136
static Level valueOf(int level) {
137
switch (level) {
138
// ordering per the highest occurrences in the jdk source
139
// finest, fine, finer, info first
140
case PlatformLogger.FINEST : return Level.FINEST;
141
case PlatformLogger.FINE : return Level.FINE;
142
case PlatformLogger.FINER : return Level.FINER;
143
case PlatformLogger.INFO : return Level.INFO;
144
case PlatformLogger.WARNING : return Level.WARNING;
145
case PlatformLogger.CONFIG : return Level.CONFIG;
146
case PlatformLogger.SEVERE : return Level.SEVERE;
147
case PlatformLogger.OFF : return Level.OFF;
148
case PlatformLogger.ALL : return Level.ALL;
149
}
150
// return the nearest Level value >= the given level,
151
// for level > SEVERE, return SEVERE and exclude OFF
152
int i = Arrays.binarySearch(LEVEL_VALUES, 0, LEVEL_VALUES.length-2, level);
153
return values()[i >= 0 ? i : (-i-1)];
154
}
155
}
156
157
private static final Level DEFAULT_LEVEL = Level.INFO;
158
private static boolean loggingEnabled;
159
static {
160
loggingEnabled = AccessController.doPrivileged(
161
new PrivilegedAction<Boolean>() {
162
public Boolean run() {
163
String cname = System.getProperty("java.util.logging.config.class");
164
String fname = System.getProperty("java.util.logging.config.file");
165
return (cname != null || fname != null);
166
}
167
});
168
169
// force loading of all JavaLoggerProxy (sub)classes to make JIT de-optimizations
170
// less probable. Don't initialize JavaLoggerProxy class since
171
// java.util.logging may not be enabled.
172
try {
173
Class.forName("sun.util.logging.PlatformLogger$DefaultLoggerProxy",
174
false,
175
PlatformLogger.class.getClassLoader());
176
Class.forName("sun.util.logging.PlatformLogger$JavaLoggerProxy",
177
false, // do not invoke class initializer
178
PlatformLogger.class.getClassLoader());
179
} catch (ClassNotFoundException ex) {
180
throw new InternalError(ex);
181
}
182
}
183
184
// Table of known loggers. Maps names to PlatformLoggers.
185
private static Map<String,WeakReference<PlatformLogger>> loggers =
186
new HashMap<>();
187
188
/**
189
* Returns a PlatformLogger of a given name.
190
*/
191
public static synchronized PlatformLogger getLogger(String name) {
192
PlatformLogger log = null;
193
WeakReference<PlatformLogger> ref = loggers.get(name);
194
if (ref != null) {
195
log = ref.get();
196
}
197
if (log == null) {
198
log = new PlatformLogger(name);
199
loggers.put(name, new WeakReference<>(log));
200
}
201
return log;
202
}
203
204
/**
205
* Initialize java.util.logging.Logger objects for all platform loggers.
206
* This method is called from LogManager.readPrimordialConfiguration().
207
*/
208
public static synchronized void redirectPlatformLoggers() {
209
if (loggingEnabled || !LoggingSupport.isAvailable()) return;
210
211
loggingEnabled = true;
212
for (Map.Entry<String, WeakReference<PlatformLogger>> entry : loggers.entrySet()) {
213
WeakReference<PlatformLogger> ref = entry.getValue();
214
PlatformLogger plog = ref.get();
215
if (plog != null) {
216
plog.redirectToJavaLoggerProxy();
217
}
218
}
219
}
220
221
/**
222
* Creates a new JavaLoggerProxy and redirects the platform logger to it
223
*/
224
private void redirectToJavaLoggerProxy() {
225
DefaultLoggerProxy lp = DefaultLoggerProxy.class.cast(this.loggerProxy);
226
JavaLoggerProxy jlp = new JavaLoggerProxy(lp.name, lp.level);
227
// the order of assignments is important
228
this.javaLoggerProxy = jlp; // isLoggable checks javaLoggerProxy if set
229
this.loggerProxy = jlp;
230
}
231
232
// DefaultLoggerProxy may be replaced with a JavaLoggerProxy object
233
// when the java.util.logging facility is enabled
234
private volatile LoggerProxy loggerProxy;
235
// javaLoggerProxy is only set when the java.util.logging facility is enabled
236
private volatile JavaLoggerProxy javaLoggerProxy;
237
private PlatformLogger(String name) {
238
if (loggingEnabled) {
239
this.loggerProxy = this.javaLoggerProxy = new JavaLoggerProxy(name);
240
} else {
241
this.loggerProxy = new DefaultLoggerProxy(name);
242
}
243
}
244
245
/**
246
* A convenience method to test if the logger is turned off.
247
* (i.e. its level is OFF).
248
*/
249
public boolean isEnabled() {
250
return loggerProxy.isEnabled();
251
}
252
253
/**
254
* Gets the name for this platform logger.
255
*/
256
public String getName() {
257
return loggerProxy.name;
258
}
259
260
/**
261
* Returns true if a message of the given level would actually
262
* be logged by this logger.
263
*/
264
public boolean isLoggable(Level level) {
265
if (level == null) {
266
throw new NullPointerException();
267
}
268
// performance-sensitive method: use two monomorphic call-sites
269
JavaLoggerProxy jlp = javaLoggerProxy;
270
return jlp != null ? jlp.isLoggable(level) : loggerProxy.isLoggable(level);
271
}
272
273
/**
274
* Get the log level that has been specified for this PlatformLogger.
275
* The result may be null, which means that this logger's
276
* effective level will be inherited from its parent.
277
*
278
* @return this PlatformLogger's level
279
*/
280
public Level level() {
281
return loggerProxy.getLevel();
282
}
283
284
/**
285
* Set the log level specifying which message levels will be
286
* logged by this logger. Message levels lower than this
287
* value will be discarded. The level value {@link #OFF}
288
* can be used to turn off logging.
289
* <p>
290
* If the new level is null, it means that this node should
291
* inherit its level from its nearest ancestor with a specific
292
* (non-null) level value.
293
*
294
* @param newLevel the new value for the log level (may be null)
295
*/
296
public void setLevel(Level newLevel) {
297
loggerProxy.setLevel(newLevel);
298
}
299
300
/**
301
* Logs a SEVERE message.
302
*/
303
public void severe(String msg) {
304
loggerProxy.doLog(Level.SEVERE, msg);
305
}
306
307
public void severe(String msg, Throwable t) {
308
loggerProxy.doLog(Level.SEVERE, msg, t);
309
}
310
311
public void severe(String msg, Object... params) {
312
loggerProxy.doLog(Level.SEVERE, msg, params);
313
}
314
315
/**
316
* Logs a WARNING message.
317
*/
318
public void warning(String msg) {
319
loggerProxy.doLog(Level.WARNING, msg);
320
}
321
322
public void warning(String msg, Throwable t) {
323
loggerProxy.doLog(Level.WARNING, msg, t);
324
}
325
326
public void warning(String msg, Object... params) {
327
loggerProxy.doLog(Level.WARNING, msg, params);
328
}
329
330
/**
331
* Logs an INFO message.
332
*/
333
public void info(String msg) {
334
loggerProxy.doLog(Level.INFO, msg);
335
}
336
337
public void info(String msg, Throwable t) {
338
loggerProxy.doLog(Level.INFO, msg, t);
339
}
340
341
public void info(String msg, Object... params) {
342
loggerProxy.doLog(Level.INFO, msg, params);
343
}
344
345
/**
346
* Logs a CONFIG message.
347
*/
348
public void config(String msg) {
349
loggerProxy.doLog(Level.CONFIG, msg);
350
}
351
352
public void config(String msg, Throwable t) {
353
loggerProxy.doLog(Level.CONFIG, msg, t);
354
}
355
356
public void config(String msg, Object... params) {
357
loggerProxy.doLog(Level.CONFIG, msg, params);
358
}
359
360
/**
361
* Logs a FINE message.
362
*/
363
public void fine(String msg) {
364
loggerProxy.doLog(Level.FINE, msg);
365
}
366
367
public void fine(String msg, Throwable t) {
368
loggerProxy.doLog(Level.FINE, msg, t);
369
}
370
371
public void fine(String msg, Object... params) {
372
loggerProxy.doLog(Level.FINE, msg, params);
373
}
374
375
/**
376
* Logs a FINER message.
377
*/
378
public void finer(String msg) {
379
loggerProxy.doLog(Level.FINER, msg);
380
}
381
382
public void finer(String msg, Throwable t) {
383
loggerProxy.doLog(Level.FINER, msg, t);
384
}
385
386
public void finer(String msg, Object... params) {
387
loggerProxy.doLog(Level.FINER, msg, params);
388
}
389
390
/**
391
* Logs a FINEST message.
392
*/
393
public void finest(String msg) {
394
loggerProxy.doLog(Level.FINEST, msg);
395
}
396
397
public void finest(String msg, Throwable t) {
398
loggerProxy.doLog(Level.FINEST, msg, t);
399
}
400
401
public void finest(String msg, Object... params) {
402
loggerProxy.doLog(Level.FINEST, msg, params);
403
}
404
405
/**
406
* Abstract base class for logging support, defining the API and common field.
407
*/
408
private static abstract class LoggerProxy {
409
final String name;
410
411
protected LoggerProxy(String name) {
412
this.name = name;
413
}
414
415
abstract boolean isEnabled();
416
417
abstract Level getLevel();
418
abstract void setLevel(Level newLevel);
419
420
abstract void doLog(Level level, String msg);
421
abstract void doLog(Level level, String msg, Throwable thrown);
422
abstract void doLog(Level level, String msg, Object... params);
423
424
abstract boolean isLoggable(Level level);
425
}
426
427
428
private static final class DefaultLoggerProxy extends LoggerProxy {
429
/**
430
* Default platform logging support - output messages to System.err -
431
* equivalent to ConsoleHandler with SimpleFormatter.
432
*/
433
private static PrintStream outputStream() {
434
return System.err;
435
}
436
437
volatile Level effectiveLevel; // effective level (never null)
438
volatile Level level; // current level set for this node (may be null)
439
440
DefaultLoggerProxy(String name) {
441
super(name);
442
this.effectiveLevel = deriveEffectiveLevel(null);
443
this.level = null;
444
}
445
446
boolean isEnabled() {
447
return effectiveLevel != Level.OFF;
448
}
449
450
Level getLevel() {
451
return level;
452
}
453
454
void setLevel(Level newLevel) {
455
Level oldLevel = level;
456
if (oldLevel != newLevel) {
457
level = newLevel;
458
effectiveLevel = deriveEffectiveLevel(newLevel);
459
}
460
}
461
462
void doLog(Level level, String msg) {
463
if (isLoggable(level)) {
464
outputStream().print(format(level, msg, null));
465
}
466
}
467
468
void doLog(Level level, String msg, Throwable thrown) {
469
if (isLoggable(level)) {
470
outputStream().print(format(level, msg, thrown));
471
}
472
}
473
474
void doLog(Level level, String msg, Object... params) {
475
if (isLoggable(level)) {
476
String newMsg = formatMessage(msg, params);
477
outputStream().print(format(level, newMsg, null));
478
}
479
}
480
481
boolean isLoggable(Level level) {
482
Level effectiveLevel = this.effectiveLevel;
483
return level.intValue() >= effectiveLevel.intValue() && effectiveLevel != Level.OFF;
484
}
485
486
// derive effective level (could do inheritance search like j.u.l.Logger)
487
private Level deriveEffectiveLevel(Level level) {
488
return level == null ? DEFAULT_LEVEL : level;
489
}
490
491
// Copied from java.util.logging.Formatter.formatMessage
492
private String formatMessage(String format, Object... parameters) {
493
// Do the formatting.
494
try {
495
if (parameters == null || parameters.length == 0) {
496
// No parameters. Just return format string.
497
return format;
498
}
499
// Is it a java.text style format?
500
// Ideally we could match with
501
// Pattern.compile("\\{\\d").matcher(format).find())
502
// However the cost is 14% higher, so we cheaply check for
503
// 1 of the first 4 parameters
504
if (format.indexOf("{0") >= 0 || format.indexOf("{1") >=0 ||
505
format.indexOf("{2") >=0|| format.indexOf("{3") >=0) {
506
return java.text.MessageFormat.format(format, parameters);
507
}
508
return format;
509
} catch (Exception ex) {
510
// Formatting failed: use format string.
511
return format;
512
}
513
}
514
515
private static final String formatString =
516
LoggingSupport.getSimpleFormat(false); // don't check logging.properties
517
518
// minimize memory allocation
519
private Date date = new Date();
520
private synchronized String format(Level level, String msg, Throwable thrown) {
521
date.setTime(System.currentTimeMillis());
522
String throwable = "";
523
if (thrown != null) {
524
StringWriter sw = new StringWriter();
525
PrintWriter pw = new PrintWriter(sw);
526
pw.println();
527
thrown.printStackTrace(pw);
528
pw.close();
529
throwable = sw.toString();
530
}
531
532
return String.format(formatString,
533
date,
534
getCallerInfo(),
535
name,
536
level.name(),
537
msg,
538
throwable);
539
}
540
541
// Returns the caller's class and method's name; best effort
542
// if cannot infer, return the logger's name.
543
private String getCallerInfo() {
544
String sourceClassName = null;
545
String sourceMethodName = null;
546
547
JavaLangAccess access = SharedSecrets.getJavaLangAccess();
548
Throwable throwable = new Throwable();
549
int depth = access.getStackTraceDepth(throwable);
550
551
String logClassName = "sun.util.logging.PlatformLogger";
552
boolean lookingForLogger = true;
553
for (int ix = 0; ix < depth; ix++) {
554
// Calling getStackTraceElement directly prevents the VM
555
// from paying the cost of building the entire stack frame.
556
StackTraceElement frame =
557
access.getStackTraceElement(throwable, ix);
558
String cname = frame.getClassName();
559
if (lookingForLogger) {
560
// Skip all frames until we have found the first logger frame.
561
if (cname.equals(logClassName)) {
562
lookingForLogger = false;
563
}
564
} else {
565
if (!cname.equals(logClassName)) {
566
// We've found the relevant frame.
567
sourceClassName = cname;
568
sourceMethodName = frame.getMethodName();
569
break;
570
}
571
}
572
}
573
574
if (sourceClassName != null) {
575
return sourceClassName + " " + sourceMethodName;
576
} else {
577
return name;
578
}
579
}
580
}
581
582
/**
583
* JavaLoggerProxy forwards all the calls to its corresponding
584
* java.util.logging.Logger object.
585
*/
586
private static final class JavaLoggerProxy extends LoggerProxy {
587
// initialize javaLevel fields for mapping from Level enum -> j.u.l.Level object
588
static {
589
for (Level level : Level.values()) {
590
level.javaLevel = LoggingSupport.parseLevel(level.name());
591
}
592
}
593
594
private final /* java.util.logging.Logger */ Object javaLogger;
595
596
JavaLoggerProxy(String name) {
597
this(name, null);
598
}
599
600
JavaLoggerProxy(String name, Level level) {
601
super(name);
602
this.javaLogger = LoggingSupport.getLogger(name);
603
if (level != null) {
604
// level has been updated and so set the Logger's level
605
LoggingSupport.setLevel(javaLogger, level.javaLevel);
606
}
607
}
608
609
void doLog(Level level, String msg) {
610
LoggingSupport.log(javaLogger, level.javaLevel, msg);
611
}
612
613
void doLog(Level level, String msg, Throwable t) {
614
LoggingSupport.log(javaLogger, level.javaLevel, msg, t);
615
}
616
617
void doLog(Level level, String msg, Object... params) {
618
if (!isLoggable(level)) {
619
return;
620
}
621
// only pass String objects to the j.u.l.Logger which may
622
// be created by untrusted code
623
int len = (params != null) ? params.length : 0;
624
Object[] sparams = new String[len];
625
for (int i = 0; i < len; i++) {
626
sparams [i] = String.valueOf(params[i]);
627
}
628
LoggingSupport.log(javaLogger, level.javaLevel, msg, sparams);
629
}
630
631
boolean isEnabled() {
632
return LoggingSupport.isLoggable(javaLogger, Level.OFF.javaLevel);
633
}
634
635
/**
636
* Returns the PlatformLogger.Level mapped from j.u.l.Level
637
* set in the logger. If the j.u.l.Logger is set to a custom Level,
638
* this method will return the nearest Level.
639
*/
640
Level getLevel() {
641
Object javaLevel = LoggingSupport.getLevel(javaLogger);
642
if (javaLevel == null) return null;
643
644
try {
645
return Level.valueOf(LoggingSupport.getLevelName(javaLevel));
646
} catch (IllegalArgumentException e) {
647
return Level.valueOf(LoggingSupport.getLevelValue(javaLevel));
648
}
649
}
650
651
void setLevel(Level level) {
652
LoggingSupport.setLevel(javaLogger, level == null ? null : level.javaLevel);
653
}
654
655
boolean isLoggable(Level level) {
656
return LoggingSupport.isLoggable(javaLogger, level.javaLevel);
657
}
658
}
659
}
660
661