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.security.AccessController; 34 import java.security.PrivilegedAction; 35 import java.util.function.Predicate; 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 // Skip all frames until we have found the first logger frame. 643 Optional<StackWalker.StackFrame> frame = new CallerFinder().get(); 644 frame.ifPresent(f -> { 645 setSourceClassName(f.getClassName()); 646 setSourceMethodName(f.getMethodName()); 647 }); 648 649 // We haven't found a suitable frame, so just punt. This is 650 // OK as we are only committed to making a "best effort" here. 651 } 652 653 /* 654 * CallerFinder is a stateful predicate. 655 */ 656 static final class CallerFinder implements Predicate<StackWalker.StackFrame> { 657 static final StackWalker WALKER = StackWalker.create(); 658 659 /** 660 * Returns StackTraceElement of the caller's frame. 661 * @return StackTraceElement of the caller's frame. 662 */ 663 Optional<StackWalker.StackFrame> get() { 664 return WALKER.walk((s) -> s.filter(this).findFirst()); 665 } 666 667 private boolean lookingForLogger = true; 668 /** 669 * Returns true if we have found the caller's frame, false if the frame 670 * must be skipped. 671 * 672 * @param t The frame info. 673 * @return true if we have found the caller's frame, false if the frame 674 * must be skipped. 675 */ 676 @Override 677 public boolean test(StackWalker.StackFrame t) { 678 final String cname = t.getClassName(); 679 // We should skip all frames until we have found the logger, 680 // because these frames could be frames introduced by e.g. custom 681 // sub classes of Handler. 682 if (lookingForLogger) { 683 lookingForLogger = !cname.equals("java.util.logging.Logger") && 684 !cname.startsWith("java.util.logging.LoggingProxyImpl") && 685 !cname.startsWith("sun.util.logging."); 686 return false; 687 } 688 // Once the logger is found - we should skip all frames that 689 // point to packages which contain artifacts that could be 690 // inserted between the logger and its caller. These could be 691 // logger wrappers from j.u.l or sun.uti.logging (e.g. the 692 // PlatformLogger or artifacts between the PlatformLogger and 693 // the actual logger) or frames inserted by use of reflection 694 // and/or doPrivileged calls. 695 return !cname.startsWith("java.util.logging.") 696 && !cname.startsWith("sun.util.logging.") 697 && !cname.startsWith("java.security.AccessController"); 698 } 699 } 700 } |