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