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