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 package java.util.logging;
27 import java.time.Instant;
28 import java.util.*;
29 import java.util.concurrent.atomic.AtomicInteger;
30 import java.util.concurrent.atomic.AtomicLong;
31 import java.io.*;
32 import java.time.Clock;
33
34 import jdk.internal.misc.JavaLangAccess;
35 import jdk.internal.misc.SharedSecrets;
36
37 /**
38 * LogRecord objects are used to pass logging requests between
39 * the logging framework and individual log Handlers.
40 * <p>
41 * When a LogRecord is passed into the logging framework it
42 * logically belongs to the framework and should no longer be
43 * used or updated by the client application.
44 * <p>
45 * Note that if the client application has not specified an
46 * explicit source method name and source class name, then the
47 * LogRecord class will infer them automatically when they are
48 * first accessed (due to a call on getSourceMethodName or
49 * getSourceClassName) by analyzing the call stack. Therefore,
50 * if a logging Handler wants to pass off a LogRecord to another
51 * thread, or to transmit it over RMI, and if it wishes to subsequently
52 * obtain method name or class name information it should call
53 * one of getSourceClassName or getSourceMethodName to force
54 * the values to be filled in.
55 * <p>
622 // use system class loader to ensure the ResourceBundle
623 // instance is a different instance than null loader uses
624 final ResourceBundle bundle =
625 ResourceBundle.getBundle(resourceBundleName,
626 Locale.getDefault(),
627 ClassLoader.getSystemClassLoader());
628 resourceBundle = bundle;
629 } catch (MissingResourceException ex) {
630 // This is not a good place to throw an exception,
631 // so we simply leave the resourceBundle null.
632 resourceBundle = null;
633 }
634 }
635
636 needToInferCaller = false;
637 }
638
639 // Private method to infer the caller's class and method names
640 private void inferCaller() {
641 needToInferCaller = false;
642 JavaLangAccess access = SharedSecrets.getJavaLangAccess();
643 Throwable throwable = new Throwable();
644 int depth = access.getStackTraceDepth(throwable);
645
646 boolean lookingForLogger = true;
647 for (int ix = 0; ix < depth; ix++) {
648 // Calling getStackTraceElement directly prevents the VM
649 // from paying the cost of building the entire stack frame.
650 StackTraceElement frame =
651 access.getStackTraceElement(throwable, ix);
652 String cname = frame.getClassName();
653 boolean isLoggerImpl = isLoggerImplFrame(cname);
654 if (lookingForLogger) {
655 // Skip all frames until we have found the first logger frame.
656 if (isLoggerImpl) {
657 lookingForLogger = false;
658 }
659 } else {
660 if (!isLoggerImpl) {
661 // skip reflection call
662 if (!cname.startsWith("java.lang.reflect.") && !cname.startsWith("sun.reflect.")) {
663 // We've found the relevant frame.
664 setSourceClassName(cname);
665 setSourceMethodName(frame.getMethodName());
666 return;
667 }
668 }
669 }
670 }
671 // We haven't found a suitable frame, so just punt. This is
672 // OK as we are only committed to making a "best effort" here.
673 }
674
675 private boolean isLoggerImplFrame(String cname) {
676 // the log record could be created for a platform logger
677 return (cname.equals("java.util.logging.Logger") ||
678 cname.startsWith("java.util.logging.LoggingProxyImpl") ||
679 cname.startsWith("sun.util.logging."));
680 }
681 }
|
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 package java.util.logging;
27 import java.time.Instant;
28 import java.util.*;
29 import java.util.concurrent.atomic.AtomicInteger;
30 import java.util.concurrent.atomic.AtomicLong;
31 import java.io.*;
32 import java.time.Clock;
33 import java.util.function.Predicate;
34
35 /**
36 * LogRecord objects are used to pass logging requests between
37 * the logging framework and individual log Handlers.
38 * <p>
39 * When a LogRecord is passed into the logging framework it
40 * logically belongs to the framework and should no longer be
41 * used or updated by the client application.
42 * <p>
43 * Note that if the client application has not specified an
44 * explicit source method name and source class name, then the
45 * LogRecord class will infer them automatically when they are
46 * first accessed (due to a call on getSourceMethodName or
47 * getSourceClassName) by analyzing the call stack. Therefore,
48 * if a logging Handler wants to pass off a LogRecord to another
49 * thread, or to transmit it over RMI, and if it wishes to subsequently
50 * obtain method name or class name information it should call
51 * one of getSourceClassName or getSourceMethodName to force
52 * the values to be filled in.
53 * <p>
620 // use system class loader to ensure the ResourceBundle
621 // instance is a different instance than null loader uses
622 final ResourceBundle bundle =
623 ResourceBundle.getBundle(resourceBundleName,
624 Locale.getDefault(),
625 ClassLoader.getSystemClassLoader());
626 resourceBundle = bundle;
627 } catch (MissingResourceException ex) {
628 // This is not a good place to throw an exception,
629 // so we simply leave the resourceBundle null.
630 resourceBundle = null;
631 }
632 }
633
634 needToInferCaller = false;
635 }
636
637 // Private method to infer the caller's class and method names
638 private void inferCaller() {
639 needToInferCaller = false;
640 // Skip all frames until we have found the first logger frame.
641 Optional<StackWalker.StackFrame> frame = new CallerFinder().get();
642 frame.ifPresent(f -> {
643 setSourceClassName(f.getClassName());
644 setSourceMethodName(f.getMethodName());
645 });
646
647 // We haven't found a suitable frame, so just punt. This is
648 // OK as we are only committed to making a "best effort" here.
649 }
650
651 /*
652 * CallerFinder is a stateful predicate.
653 */
654 static final class CallerFinder implements Predicate<StackWalker.StackFrame> {
655 static final StackWalker WALKER = StackWalker.getInstance();
656
657 /**
658 * Returns StackTraceElement of the caller's frame.
659 * @return StackTraceElement of the caller's frame.
660 */
661 Optional<StackWalker.StackFrame> get() {
662 return WALKER.walk((s) -> s.filter(this).findFirst());
663 }
664
665 private boolean lookingForLogger = true;
666 /**
667 * Returns true if we have found the caller's frame, false if the frame
668 * must be skipped.
669 *
670 * @param t The frame info.
671 * @return true if we have found the caller's frame, false if the frame
672 * must be skipped.
673 */
674 @Override
675 public boolean test(StackWalker.StackFrame t) {
676 final String cname = t.getClassName();
677 // We should skip all frames until we have found the logger,
678 // because these frames could be frames introduced by e.g. custom
679 // sub classes of Handler.
680 if (lookingForLogger) {
681 lookingForLogger = !cname.equals("java.util.logging.Logger") &&
682 !cname.startsWith("java.util.logging.LoggingProxyImpl") &&
683 !cname.startsWith("sun.util.logging.");
684 return false;
685 }
686 // Once the logger is found - we should skip all frames that
687 // point to packages which contain artifacts that could be
688 // inserted between the logger and its caller. These could be
689 // logger wrappers from j.u.l or sun.uti.logging (e.g. the
690 // PlatformLogger or artifacts between the PlatformLogger and
691 // the actual logger) or frames inserted by use of reflection
692 // and/or doPrivileged calls.
693 return !cname.startsWith("java.util.logging.")
694 && !cname.startsWith("sun.util.logging.")
695 && !cname.startsWith("java.security.AccessController");
696 }
697 }
698 }
|