1 /* 2 * Copyright (c) 2015, 2019, 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 28 import java.lang.StackWalker.StackFrame; 29 import java.lang.invoke.MethodType; 30 31 class StackFrameInfo implements StackFrame { 32 33 // Android-removed: libcore doesn't have JavaLangInvokeAccess yet. 34 // private static final JavaLangInvokeAccess JLIA = 35 // SharedSecrets.getJavaLangInvokeAccess(); 36 37 private final boolean retainClassRef; 38 // Android-removed: Unused internal fields. 39 // private final Object memberName; // MemberName initialized by VM 40 private int bci; // initialized by VM to >= 0 41 private volatile StackTraceElement ste; 42 43 // Android-added: Add Android-specific internal fields. 44 private Class<?> declaringClass; // initialized by VM 45 private MethodType methodType; // initialized by VM 46 private String methodName; // initialized by VM 47 private String fileName; // initialized by VM 48 private int lineNumber; // initialized by VM 49 50 /* 51 * Construct an empty StackFrameInfo object that will be filled by the VM 52 * during stack walking. 53 * 54 * @see StackStreamFactory.AbstractStackWalker#callStackWalk 55 * @see StackStreamFactory.AbstractStackWalker#fetchStackFrames 56 */ StackFrameInfo(StackWalker walker)57 StackFrameInfo(StackWalker walker) { 58 this.retainClassRef = walker.retainClassRef; 59 // Android-removed: Unused internal fields. 60 // this.memberName = JLIA.newMemberName(); 61 } 62 63 // Android-added: Additional constructor StackFrameInfo(boolean retainClassRef)64 StackFrameInfo(boolean retainClassRef) { 65 this.retainClassRef = retainClassRef; 66 } 67 68 69 // package-private called by StackStreamFactory to skip 70 // the capability check declaringClass()71 Class<?> declaringClass() { 72 // Android-changed: Android own implementation. 73 // return JLIA.getDeclaringClass(memberName); 74 return declaringClass; 75 } 76 77 // ----- implementation of StackFrame methods 78 79 @Override getClassName()80 public String getClassName() { 81 return declaringClass().getName(); 82 } 83 84 @Override getDeclaringClass()85 public Class<?> getDeclaringClass() { 86 ensureRetainClassRefEnabled(); 87 return declaringClass(); 88 } 89 90 @Override getMethodName()91 public String getMethodName() { 92 // Android-changed: Android own implementation. 93 // return JLIA.getName(memberName); 94 return methodName; 95 } 96 97 @Override getMethodType()98 public MethodType getMethodType() { 99 ensureRetainClassRefEnabled(); 100 // Android-changed: Android own implementation. 101 // return JLIA.getMethodType(memberName); 102 return methodType; 103 } 104 105 @Override getDescriptor()106 public String getDescriptor() { 107 // Android-changed: Android own implementation. 108 // return JLIA.getMethodDescriptor(memberName); 109 return methodType.toMethodDescriptorString(); 110 } 111 112 @Override getByteCodeIndex()113 public int getByteCodeIndex() { 114 // bci not available for native methods 115 if (isNativeMethod()) 116 return -1; 117 118 return bci; 119 } 120 121 @Override getFileName()122 public String getFileName() { 123 // Android-changed: Android own implementation. 124 // return toStackTraceElement().getFileName(); 125 return fileName; 126 } 127 128 @Override getLineNumber()129 public int getLineNumber() { 130 // line number not available for native methods 131 if (isNativeMethod()) 132 return -2; 133 134 // Android-changed: Android own implementation. 135 // return toStackTraceElement().getLineNumber(); 136 return lineNumber; 137 } 138 139 140 @Override isNativeMethod()141 public boolean isNativeMethod() { 142 // Android-changed: Android own implementation. 143 // return JLIA.isNative(memberName); 144 // StackTraceElement.isNativeMethod() uses -2 in line number to indicate native method. 145 return lineNumber == -2; 146 } 147 148 @Override toString()149 public String toString() { 150 return toStackTraceElement().toString(); 151 } 152 153 @Override toStackTraceElement()154 public StackTraceElement toStackTraceElement() { 155 StackTraceElement s = ste; 156 if (s == null) { 157 synchronized (this) { 158 s = ste; 159 if (s == null) { 160 ste = s = StackTraceElement.of(this); 161 } 162 } 163 } 164 return s; 165 } 166 ensureRetainClassRefEnabled()167 private void ensureRetainClassRefEnabled() { 168 if (!retainClassRef) { 169 throw new UnsupportedOperationException("No access to RETAIN_CLASS_REFERENCE"); 170 } 171 } 172 } 173