1/*
2 * Copyright (c) 2015, 2016, 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 */
25package java.lang;
26
27import jdk.internal.misc.JavaLangInvokeAccess;
28import jdk.internal.misc.SharedSecrets;
29
30import static java.lang.StackWalker.Option.*;
31import java.lang.StackWalker.StackFrame;
32
33class StackFrameInfo implements StackFrame {
34    private final static JavaLangInvokeAccess JLIA =
35        SharedSecrets.getJavaLangInvokeAccess();
36
37    // Footprint improvement: MemberName::clazz can replace
38    // StackFrameInfo::declaringClass.
39
40    private final StackWalker walker;
41    private final Class<?> declaringClass;
42    private final Object memberName;
43    private final short bci;
44    private volatile StackTraceElement ste;
45
46    /*
47     * Create StackFrameInfo for StackFrameTraverser and LiveStackFrameTraverser
48     * to use
49     */
50    StackFrameInfo(StackWalker walker) {
51        this.walker = walker;
52        this.declaringClass = null;
53        this.bci = -1;
54        this.memberName = JLIA.newMemberName();
55    }
56
57    // package-private called by StackStreamFactory to skip
58    // the capability check
59    Class<?> declaringClass() {
60        return declaringClass;
61    }
62
63    // ----- implementation of StackFrame methods
64
65    @Override
66    public String getClassName() {
67        return declaringClass.getName();
68    }
69
70    @Override
71    public Class<?> getDeclaringClass() {
72        walker.ensureAccessEnabled(RETAIN_CLASS_REFERENCE);
73        return declaringClass;
74    }
75
76    @Override
77    public String getMethodName() {
78        return JLIA.getName(memberName);
79    }
80
81    @Override
82    public int getByteCodeIndex() {
83        // bci not available for native methods
84        if (isNativeMethod())
85            return -1;
86
87        return bci;
88    }
89
90    @Override
91    public String getFileName() {
92        return toStackTraceElement().getFileName();
93    }
94
95    @Override
96    public int getLineNumber() {
97        // line number not available for native methods
98        if (isNativeMethod())
99            return -2;
100
101        return toStackTraceElement().getLineNumber();
102    }
103
104
105    @Override
106    public boolean isNativeMethod() {
107        return JLIA.isNative(memberName);
108    }
109
110    @Override
111    public String toString() {
112        return toStackTraceElement().toString();
113    }
114
115    @Override
116    public StackTraceElement toStackTraceElement() {
117        StackTraceElement s = ste;
118        if (s == null) {
119            synchronized (this) {
120                s = ste;
121                if (s == null) {
122                    ste = s = StackTraceElement.of(this);
123                }
124            }
125        }
126        return s;
127    }
128}
129