1 /* 2 * Copyright (c) 2015, 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 package java.lang; 26 27 import jdk.internal.misc.JavaLangInvokeAccess; 28 import jdk.internal.misc.SharedSecrets; 29 30 import static java.lang.StackWalker.Option.*; 31 import java.lang.StackWalker.StackFrame; 32 import java.util.Optional; 33 import java.util.OptionalInt; 34 35 class StackFrameInfo implements StackFrame { 36 private final static JavaLangInvokeAccess jlInvokeAccess = 37 SharedSecrets.getJavaLangInvokeAccess(); 38 39 // -XX:+MemberNameInStackFrame will initialize MemberName and all other fields; 40 // otherwise, StackFrameInfo::mid will be set. This is temporary to enable 41 // performance measurement 42 // 43 // Footprint improvement: MemberName::clazz and MemberName::name 44 // can replace StackFrameInfo::declaringClass and StackFrameInfo::methodName 45 // Currently VM sets StackFrameInfo::methodName instead of expanding MemberName::name 46 47 final StackWalker walker; 48 final Class<?> declaringClass; 49 final Object memberName; 50 final int bci; 51 52 // Set when -XX:-MemberNameInStackFrame 53 private final int mid; 54 55 // methodName, fileName, and lineNumber will be lazily set by the VM 56 // when first requested. 57 private String methodName; 58 private String fileName = null; // default for unavailable filename 59 private int lineNumber = -1; // default for unavailable lineNumber 60 61 /* 62 * Create StackFrameInfo for StackFrameTraverser and LiveStackFrameTraverser 63 * to use 64 */ 65 StackFrameInfo(StackWalker walker) { 66 this.walker = walker; 67 this.declaringClass = null; 68 this.mid = 0; 69 this.bci = -1; 70 this.memberName = jlInvokeAccess.newMemberName(); 71 } 72 73 @Override 74 public String getClassName() { 75 return declaringClass.getName(); 76 } 77 78 @Override 79 public Class<?> getDeclaringClass() { 80 walker.ensureAccessEnabled(RETAIN_CLASS_REFERENCE); 81 return declaringClass; 82 } 83 84 // Call the VM to set methodName, lineNumber, and fileName 85 private synchronized void ensureMethodInfoInitialized() { 86 if (methodName == null) { 87 setMethodInfo(); 88 } 89 } 90 91 @Override 92 public String getMethodName() { 93 ensureMethodInfoInitialized(); 94 return methodName; 95 } 96 97 @Override 98 public Optional<String> getFileName() { 99 ensureMethodInfoInitialized(); 100 return fileName != null ? Optional.of(fileName) : Optional.empty(); 101 } 102 103 @Override 104 public OptionalInt getLineNumber() { 105 ensureMethodInfoInitialized(); 106 return lineNumber != -1 ? OptionalInt.of(lineNumber) : OptionalInt.empty(); 107 } 108 109 @Override 110 public boolean isNativeMethod() { 111 ensureMethodInfoInitialized(); 112 return lineNumber == -2; 113 } 114 115 @Override 116 public String toString() { 117 ensureMethodInfoInitialized(); 118 // same format about StackTraceElement::toString 119 return getClassName() + "." + getMethodName() + 120 (isNativeMethod() ? "(Native Method)" : 121 (fileName != null && lineNumber >= 0 ? 122 "(" + fileName + ":" + lineNumber + ")" : 123 (fileName != null ? "("+fileName+")" : "(Unknown Source)"))); 124 } 125 126 /** 127 * Lazily initialize method name, file name, line number 128 */ 129 private native void setMethodInfo(); 130 131 /** 132 * Fill in source file name and line number of the given StackFrame array. 133 */ 134 static native void fillInStackFrames(int startIndex, 135 Object[] stackframes, 136 int fromIndex, int toIndex); 137 }