< prev index next >

jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java

Print this page




  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.time.Clock;
  36 import java.time.Instant;
  37 import java.time.ZoneId;
  38 import java.time.ZonedDateTime;
  39 import java.util.Arrays;
  40 import java.util.HashMap;
  41 import java.util.Map;
  42 import jdk.internal.misc.JavaLangAccess;
  43 import jdk.internal.misc.SharedSecrets;
  44 
  45 /**
  46  * Platform logger provides an API for the JRE components to log
  47  * messages.  This enables the runtime components to eliminate the
  48  * static dependency of the logging facility and also defers the
  49  * java.util.logging initialization until it is enabled.
  50  * In addition, the PlatformLogger API can be used if the logging
  51  * module does not exist.
  52  *
  53  * If the logging facility is not enabled, the platform loggers
  54  * will output log messages per the default logging configuration
  55  * (see below). In this implementation, it does not log the
  56  * the stack frame information issuing the log message.
  57  *
  58  * When the logging facility is enabled (at startup or runtime),
  59  * the java.util.logging.Logger will be created for each platform
  60  * logger and all log messages will be forwarded to the Logger
  61  * to handle.
  62  *
  63  * Logging facility is "enabled" when one of the following


 522             ZonedDateTime zdt = ZonedDateTime.now(zoneId);
 523             String throwable = "";
 524             if (thrown != null) {
 525                 StringWriter sw = new StringWriter();
 526                 PrintWriter pw = new PrintWriter(sw);
 527                 pw.println();
 528                 thrown.printStackTrace(pw);
 529                 pw.close();
 530                 throwable = sw.toString();
 531             }
 532 
 533             return String.format(formatString,
 534                                  zdt,
 535                                  getCallerInfo(),
 536                                  name,
 537                                  level.name(),
 538                                  msg,
 539                                  throwable);
 540         }
 541 
 542         // Returns the caller's class and method's name; best effort
 543         // if cannot infer, return the logger's name.
 544         private String getCallerInfo() {
 545             String sourceClassName = null;
 546             String sourceMethodName = null;
 547 
 548             JavaLangAccess access = SharedSecrets.getJavaLangAccess();
 549             Throwable throwable = new Throwable();
 550             int depth = access.getStackTraceDepth(throwable);
 551 
 552             String logClassName = "sun.util.logging.PlatformLogger";
 553             boolean lookingForLogger = true;
 554             for (int ix = 0; ix < depth; ix++) {
 555                 // Calling getStackTraceElement directly prevents the VM
 556                 // from paying the cost of building the entire stack frame.
 557                 StackTraceElement frame =
 558                     access.getStackTraceElement(throwable, ix);
 559                 String cname = frame.getClassName();
 560                 if (lookingForLogger) {
 561                     // Skip all frames until we have found the first logger frame.
 562                     if (cname.equals(logClassName)) {
 563                         lookingForLogger = false;
 564                     }
 565                 } else {
 566                     if (!cname.equals(logClassName)) {
 567                         // We've found the relevant frame.
 568                         sourceClassName = cname;
 569                         sourceMethodName = frame.getMethodName();
 570                         break;














 571                     }










 572                 }
 573             }
 574 
 575             if (sourceClassName != null) {
 576                 return sourceClassName + " " + sourceMethodName;
 577             } else {
 578                 return name;
 579             }
 580         }
 581     }
 582 
 583     /**
 584      * JavaLoggerProxy forwards all the calls to its corresponding
 585      * java.util.logging.Logger object.
 586      */
 587     private static final class JavaLoggerProxy extends LoggerProxy {
 588         // initialize javaLevel fields for mapping from Level enum -> j.u.l.Level object
 589         static {
 590             for (Level level : Level.values()) {
 591                 level.javaLevel = LoggingSupport.parseLevel(level.name());
 592             }
 593         }
 594 
 595         private final /* java.util.logging.Logger */ Object javaLogger;
 596 
 597         JavaLoggerProxy(String name) {
 598             this(name, null);
 599         }




  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.time.ZoneId;
  36 import java.time.ZonedDateTime;
  37 import java.util.Arrays;
  38 import java.util.HashMap;
  39 import java.util.Map;
  40 import java.util.Optional;
  41 import java.util.function.Predicate;
  42 
  43 /**
  44  * Platform logger provides an API for the JRE components to log
  45  * messages.  This enables the runtime components to eliminate the
  46  * static dependency of the logging facility and also defers the
  47  * java.util.logging initialization until it is enabled.
  48  * In addition, the PlatformLogger API can be used if the logging
  49  * module does not exist.
  50  *
  51  * If the logging facility is not enabled, the platform loggers
  52  * will output log messages per the default logging configuration
  53  * (see below). In this implementation, it does not log the
  54  * the stack frame information issuing the log message.
  55  *
  56  * When the logging facility is enabled (at startup or runtime),
  57  * the java.util.logging.Logger will be created for each platform
  58  * logger and all log messages will be forwarded to the Logger
  59  * to handle.
  60  *
  61  * Logging facility is "enabled" when one of the following


 520             ZonedDateTime zdt = ZonedDateTime.now(zoneId);
 521             String throwable = "";
 522             if (thrown != null) {
 523                 StringWriter sw = new StringWriter();
 524                 PrintWriter pw = new PrintWriter(sw);
 525                 pw.println();
 526                 thrown.printStackTrace(pw);
 527                 pw.close();
 528                 throwable = sw.toString();
 529             }
 530 
 531             return String.format(formatString,
 532                                  zdt,
 533                                  getCallerInfo(),
 534                                  name,
 535                                  level.name(),
 536                                  msg,
 537                                  throwable);
 538         }
 539 
 540         /*
 541          * CallerFinder is a stateful predicate.
 542          */
 543         static final class CallerFinder implements Predicate<StackWalker.StackFrame> {
 544             static final StackWalker WALKER = StackWalker.getInstance();
 545 
 546             /**
 547              * Returns StackFrame of the caller's frame.
 548              * @return StackFrame of the caller's frame.
 549              */
 550             Optional<StackWalker.StackFrame> get() {
 551                 return WALKER.walk(s -> s.filter(this).findFirst());










 552             }
 553 
 554             private boolean lookingForLogger = true;
 555 
 556             /**
 557              * Returns true if we have found the caller's frame, false if the frame
 558              * must be skipped.
 559              *
 560              * @param t The frame info.
 561              * @return true if we have found the caller's frame, false if the frame
 562              * must be skipped.
 563              */
 564             @Override
 565             public boolean test(StackWalker.StackFrame t) {
 566                 final String cname = t.getClassName();
 567                 // We should skip all frames until we have found the logger,
 568                 // because these frames could be frames introduced by e.g. custom
 569                 // sub classes of Handler.
 570                 if (lookingForLogger) {
 571                     lookingForLogger = !cname.equals("sun.util.logging.PlatformLogger");
 572                     return false;
 573                 }
 574                 // Once the logger is found - we should skip all frames that
 575                 // point to packages which contain artifacts that could be
 576                 // inserted between the logger and its caller. These could be
 577                 // logger wrappers from j.u.l or sun.util.logging (e.g. the
 578                 // PlatformLogger or artifacts between the PlatformLogger and
 579                 // the actual logger) or frames inserted by use of reflection
 580                 // and/or doPrivileged calls.
 581                 return !cname.startsWith("java.util.logging.")
 582                         && !cname.startsWith("sun.util.logging.")
 583                         && !cname.startsWith("java.security.AccessController");
 584             }
 585         }
 586 
 587         private String getCallerInfo() {
 588             Optional<StackWalker.StackFrame> frame = new CallerFinder().get();
 589             return frame.map(f -> f.getClassName() + " " + f.getMethodName()).orElse(name);


 590         }
 591     }
 592 
 593     /**
 594      * JavaLoggerProxy forwards all the calls to its corresponding
 595      * java.util.logging.Logger object.
 596      */
 597     private static final class JavaLoggerProxy extends LoggerProxy {
 598         // initialize javaLevel fields for mapping from Level enum -> j.u.l.Level object
 599         static {
 600             for (Level level : Level.values()) {
 601                 level.javaLevel = LoggingSupport.parseLevel(level.name());
 602             }
 603         }
 604 
 605         private final /* java.util.logging.Logger */ Object javaLogger;
 606 
 607         JavaLoggerProxy(String name) {
 608             this(name, null);
 609         }


< prev index next >