StackTraceElement.java revision 14138:0dfea12d7199
1/*
2 * Copyright (c) 2000, 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 */
25
26package java.lang;
27
28import java.util.Objects;
29
30/**
31 * An element in a stack trace, as returned by {@link
32 * Throwable#getStackTrace()}.  Each element represents a single stack frame.
33 * All stack frames except for the one at the top of the stack represent
34 * a method invocation.  The frame at the top of the stack represents the
35 * execution point at which the stack trace was generated.  Typically,
36 * this is the point at which the throwable corresponding to the stack trace
37 * was created.
38 *
39 * @since  1.4
40 * @author Josh Bloch
41 */
42public final class StackTraceElement implements java.io.Serializable {
43    // Normally initialized by VM (public constructor added in 1.5)
44    private String moduleName;
45    private String moduleVersion;
46    private String declaringClass;
47    private String methodName;
48    private String fileName;
49    private int    lineNumber;
50
51    /**
52     * Creates a stack trace element representing the specified execution
53     * point. The {@link #getModuleName module name} and {@link
54     * #getModuleVersion module version} of the stack trace element will
55     * be {@code null}.
56     *
57     * @param declaringClass the fully qualified name of the class containing
58     *        the execution point represented by the stack trace element
59     * @param methodName the name of the method containing the execution point
60     *        represented by the stack trace element
61     * @param fileName the name of the file containing the execution point
62     *         represented by the stack trace element, or {@code null} if
63     *         this information is unavailable
64     * @param lineNumber the line number of the source line containing the
65     *         execution point represented by this stack trace element, or
66     *         a negative number if this information is unavailable. A value
67     *         of -2 indicates that the method containing the execution point
68     *         is a native method
69     * @throws NullPointerException if {@code declaringClass} or
70     *         {@code methodName} is null
71     * @since 1.5
72     */
73    public StackTraceElement(String declaringClass, String methodName,
74                             String fileName, int lineNumber) {
75        this(null, null, declaringClass, methodName, fileName, lineNumber);
76    }
77
78    /**
79     * Creates a stack trace element representing the specified execution
80     * point.
81     *
82     * @param moduleName the module name if the class containing the
83     *        execution point represented by the stack trace is in a named
84     *        module; can be {@code null}
85     * @param moduleVersion the module version if the class containing the
86     *        execution point represented by the stack trace is in a named
87     *        module that has a version; can be {@code null}
88     * @param declaringClass the fully qualified name of the class containing
89     *        the execution point represented by the stack trace element
90     * @param methodName the name of the method containing the execution point
91     *        represented by the stack trace element
92     * @param fileName the name of the file containing the execution point
93     *        represented by the stack trace element, or {@code null} if
94     *        this information is unavailable
95     * @param lineNumber the line number of the source line containing the
96     *        execution point represented by this stack trace element, or
97     *        a negative number if this information is unavailable. A value
98     *        of -2 indicates that the method containing the execution point
99     *        is a native method
100     * @throws NullPointerException if {@code declaringClass} is {@code null}
101     *         or {@code methodName} is {@code null}
102     * @since 9
103     */
104    public StackTraceElement(String moduleName, String moduleVersion,
105                             String declaringClass, String methodName,
106                             String fileName, int lineNumber) {
107        this.moduleName     = moduleName;
108        this.moduleVersion  = moduleVersion;
109        this.declaringClass = Objects.requireNonNull(declaringClass, "Declaring class is null");
110        this.methodName     = Objects.requireNonNull(methodName, "Method name is null");
111        this.fileName       = fileName;
112        this.lineNumber     = lineNumber;
113    }
114
115
116    /**
117     * Creates an empty stack frame element to be filled in by Throwable.
118     */
119    StackTraceElement() { }
120
121    /**
122     * Returns the name of the source file containing the execution point
123     * represented by this stack trace element.  Generally, this corresponds
124     * to the {@code SourceFile} attribute of the relevant {@code class}
125     * file (as per <i>The Java Virtual Machine Specification</i>, Section
126     * 4.7.7).  In some systems, the name may refer to some source code unit
127     * other than a file, such as an entry in source repository.
128     *
129     * @return the name of the file containing the execution point
130     *         represented by this stack trace element, or {@code null} if
131     *         this information is unavailable.
132     */
133    public String getFileName() {
134        return fileName;
135    }
136
137    /**
138     * Returns the line number of the source line containing the execution
139     * point represented by this stack trace element.  Generally, this is
140     * derived from the {@code LineNumberTable} attribute of the relevant
141     * {@code class} file (as per <i>The Java Virtual Machine
142     * Specification</i>, Section 4.7.8).
143     *
144     * @return the line number of the source line containing the execution
145     *         point represented by this stack trace element, or a negative
146     *         number if this information is unavailable.
147     */
148    public int getLineNumber() {
149        return lineNumber;
150    }
151
152    /**
153     * Returns the module name of the module containing the execution point
154     * represented by this stack trace element.
155     *
156     * @return the module name of the {@code Module} containing the execution
157     *         point represented by this stack trace element; {@code null}
158     *         if the module name is not available.
159     * @since 9
160     * @see java.lang.reflect.Module#getName()
161     */
162    public String getModuleName() {
163        return moduleName;
164    }
165
166    /**
167     * Returns the module version of the module containing the execution point
168     * represented by this stack trace element.
169     *
170     * @return the module version of the {@code Module} containing the execution
171     *         point represented by this stack trace element; {@code null}
172     *         if the module version is not available.
173     * @since 9
174     * @see java.lang.module.ModuleDescriptor.Version
175     */
176    public String getModuleVersion() {
177        return moduleVersion;
178    }
179
180    /**
181     * Returns the fully qualified name of the class containing the
182     * execution point represented by this stack trace element.
183     *
184     * @return the fully qualified name of the {@code Class} containing
185     *         the execution point represented by this stack trace element.
186     */
187    public String getClassName() {
188        return declaringClass;
189    }
190
191    /**
192     * Returns the name of the method containing the execution point
193     * represented by this stack trace element.  If the execution point is
194     * contained in an instance or class initializer, this method will return
195     * the appropriate <i>special method name</i>, {@code <init>} or
196     * {@code <clinit>}, as per Section 3.9 of <i>The Java Virtual
197     * Machine Specification</i>.
198     *
199     * @return the name of the method containing the execution point
200     *         represented by this stack trace element.
201     */
202    public String getMethodName() {
203        return methodName;
204    }
205
206    /**
207     * Returns true if the method containing the execution point
208     * represented by this stack trace element is a native method.
209     *
210     * @return {@code true} if the method containing the execution point
211     *         represented by this stack trace element is a native method.
212     */
213    public boolean isNativeMethod() {
214        return lineNumber == -2;
215    }
216
217    /**
218     * Returns a string representation of this stack trace element.  The
219     * format of this string depends on the implementation, but the following
220     * examples may be regarded as typical:
221     * <ul>
222     * <li>
223     *   {@code "MyClass.mash(my.module@9.0/MyClass.java:101)"} - Here,
224     *   {@code "MyClass"} is the <i>fully-qualified name</i> of the class
225     *   containing the execution point represented by this stack trace element,
226     *   {@code "mash"} is the name of the method containing the execution
227     *   point, {@code "my.module"} is the module name, {@code "9.0"} is the
228     *   module version, and {@code "101"} is the line number of the source
229     *   line containing the execution point.
230     * <li>
231     *   {@code "MyClass.mash(my.module@9.0/MyClass.java)"} - As above, but the
232     *   line number is unavailable.
233     * <li>
234     *   {@code "MyClass.mash(my.module@9.0/Unknown Source)"} - As above, but
235     *   neither the file name nor the line  number are available.
236     * <li>
237     *   {@code "MyClass.mash(my.module@9.0/Native Method)"} - As above, but
238     *   neither the file name nor the line  number are available, and the
239     *   method containing the execution point is known to be a native method.
240     * </ul>
241     * If the execution point is not in a named module, {@code "my.module@9.0/"}
242     * will be omitted from the above.
243     *
244     * @see    Throwable#printStackTrace()
245     */
246    public String toString() {
247        String mid = "";
248        if (moduleName != null) {
249            mid = moduleName;
250            if (moduleVersion != null)
251                mid += "@" + moduleVersion;
252            mid += "/";
253        }
254        return getClassName() + "." + methodName + "(" + mid +
255             (isNativeMethod() ? "Native Method)" :
256              (fileName != null && lineNumber >= 0 ?
257               fileName + ":" + lineNumber + ")" :
258                (fileName != null ?  ""+fileName+")" : "Unknown Source)")));
259    }
260
261    /**
262     * Returns true if the specified object is another
263     * {@code StackTraceElement} instance representing the same execution
264     * point as this instance.  Two stack trace elements {@code a} and
265     * {@code b} are equal if and only if:
266     * <pre>{@code
267     *     equals(a.getFileName(), b.getFileName()) &&
268     *     a.getLineNumber() == b.getLineNumber()) &&
269     *     equals(a.getModuleName(), b.getModuleName()) &&
270     *     equals(a.getModuleVersion(), b.getModuleVersion()) &&
271     *     equals(a.getClassName(), b.getClassName()) &&
272     *     equals(a.getMethodName(), b.getMethodName())
273     * }</pre>
274     * where {@code equals} has the semantics of {@link
275     * java.util.Objects#equals(Object, Object) Objects.equals}.
276     *
277     * @param  obj the object to be compared with this stack trace element.
278     * @return true if the specified object is another
279     *         {@code StackTraceElement} instance representing the same
280     *         execution point as this instance.
281     */
282    public boolean equals(Object obj) {
283        if (obj==this)
284            return true;
285        if (!(obj instanceof StackTraceElement))
286            return false;
287        StackTraceElement e = (StackTraceElement)obj;
288        return e.declaringClass.equals(declaringClass) &&
289            Objects.equals(moduleName, e.moduleName) &&
290            Objects.equals(moduleVersion, e.moduleVersion) &&
291            e.lineNumber == lineNumber &&
292            Objects.equals(methodName, e.methodName) &&
293            Objects.equals(fileName, e.fileName);
294    }
295
296    /**
297     * Returns a hash code value for this stack trace element.
298     */
299    public int hashCode() {
300        int result = 31*declaringClass.hashCode() + methodName.hashCode();
301        result = 31*result + Objects.hashCode(moduleName);
302        result = 31*result + Objects.hashCode(moduleVersion);
303        result = 31*result + Objects.hashCode(fileName);
304        result = 31*result + lineNumber;
305        return result;
306    }
307
308    private static final long serialVersionUID = 6992337162326171013L;
309}
310