• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package java.lang;
19 
20 import java.io.Serializable;
21 
22 /**
23  * A representation of a single stack frame. Arrays of {@code StackTraceElement}
24  * are stored in {@link Throwable} objects to represent the whole state of the
25  * call stack at the time a {@code Throwable} gets thrown.
26  *
27  * @see Throwable#getStackTrace()
28  */
29 public final class StackTraceElement implements Serializable {
30 
31     private static final long serialVersionUID = 6992337162326171013L;
32 
33     // BEGIN android-added
34     private static final int NATIVE_LINE_NUMBER = -2;
35     // END android-added
36 
37     String declaringClass;
38 
39     String methodName;
40 
41     String fileName;
42 
43     int lineNumber;
44 
45     /**
46      * Constructs a new {@code StackTraceElement} for a specified execution
47      * point.
48      *
49      * @param cls
50      *            the fully qualified name of the class where execution is at.
51      * @param method
52      *            the name of the method where execution is at.
53      * @param file
54      *            The name of the file where execution is at or {@code null}.
55      * @param line
56      *            the line of the file where execution is at, a negative number
57      *            if unknown or {@code -2} if the execution is in a native
58      *            method.
59      * @throws NullPointerException
60      *             if {@code cls} or {@code method} is {@code null}.
61      */
StackTraceElement(String cls, String method, String file, int line)62     public StackTraceElement(String cls, String method, String file, int line) {
63         super();
64         if (cls == null || method == null) {
65             throw new NullPointerException();
66         }
67         declaringClass = cls;
68         methodName = method;
69         fileName = file;
70         lineNumber = line;
71     }
72 
73     /**
74      * <p>
75      * Private, nullary constructor for VM use only.
76      * </p>
77      */
StackTraceElement()78     private StackTraceElement() {
79         super();
80     }
81 
82     /**
83      * Compares this instance with the specified object and indicates if they
84      * are equal. In order to be equal, the following conditions must be
85      * fulfilled:
86      * <ul>
87      * <li>{@code obj} must be a stack trace element,</li>
88      * <li>the method names of this stack trace element and of {@code obj} must
89      * not be {@code null},</li>
90      * <li>the class, method and file names as well as the line number of this
91      * stack trace element and of {@code obj} must be equal.</li>
92      * </ul>
93      *
94      * @param obj
95      *            the object to compare this instance with.
96      * @return {@code true} if the specified object is equal to this
97      *         {@code StackTraceElement}; {@code false} otherwise.
98      * @see #hashCode
99      */
100     @Override
equals(Object obj)101     public boolean equals(Object obj) {
102         if (!(obj instanceof StackTraceElement)) {
103             return false;
104         }
105         StackTraceElement castObj = (StackTraceElement) obj;
106 
107         /*
108          * Unknown methods are never equal to anything (not strictly to spec,
109          * but spec does not allow null method/class names)
110          */
111         if ((methodName == null) || (castObj.methodName == null)) {
112             return false;
113         }
114 
115         if (!getMethodName().equals(castObj.getMethodName())) {
116             return false;
117         }
118         if (!getClassName().equals(castObj.getClassName())) {
119             return false;
120         }
121         String localFileName = getFileName();
122         if (localFileName == null) {
123             if (castObj.getFileName() != null) {
124                 return false;
125             }
126         } else {
127             if (!localFileName.equals(castObj.getFileName())) {
128                 return false;
129             }
130         }
131         if (getLineNumber() != castObj.getLineNumber()) {
132             return false;
133         }
134 
135         return true;
136     }
137 
138     /**
139      * Returns the fully qualified name of the class belonging to this
140      * {@code StackTraceElement}.
141      *
142      * @return the fully qualified type name of the class
143      */
getClassName()144     public String getClassName() {
145         return (declaringClass == null) ? "<unknown class>" : declaringClass;
146     }
147 
148     /**
149      * Returns the name of the Java source file containing class belonging to
150      * this {@code StackTraceElement}.
151      *
152      * @return the name of the file, or {@code null} if this information is not
153      *         available.
154      */
getFileName()155     public String getFileName() {
156         return fileName;
157     }
158 
159     /**
160      * Returns the line number in the source for the class belonging to this
161      * {@code StackTraceElement}.
162      *
163      * @return the line number, or a negative number if this information is not
164      *         available.
165      */
getLineNumber()166     public int getLineNumber() {
167         return lineNumber;
168     }
169 
170     /**
171      * Returns the name of the method belonging to this {@code
172      * StackTraceElement}.
173      *
174      * @return the name of the method, or "<unknown method>" if this information
175      *         is not available.
176      */
getMethodName()177     public String getMethodName() {
178         return (methodName == null) ? "<unknown method>" : methodName;
179     }
180 
181     @Override
hashCode()182     public int hashCode() {
183         /*
184          * Either both methodName and declaringClass are null, or neither are
185          * null.
186          */
187         if (methodName == null) {
188             // all unknown methods hash the same
189             return 0;
190         }
191         // declaringClass never null if methodName is non-null
192         return methodName.hashCode() ^ declaringClass.hashCode();
193     }
194 
195     /**
196      * Indicates if the method name returned by {@link #getMethodName()} is
197      * implemented as a native method.
198      *
199      * @return {@code true} if the method in which this stack trace element is
200      *         executing is a native method; {@code false} otherwise.
201      */
isNativeMethod()202     public boolean isNativeMethod() {
203         // BEGIN android-changed
204         return lineNumber == NATIVE_LINE_NUMBER;
205         // END android-changed
206     }
207 
208     @Override
toString()209     public String toString() {
210         StringBuilder buf = new StringBuilder(80);
211 
212         buf.append(getClassName());
213         buf.append('.');
214         buf.append(getMethodName());
215 
216         if (isNativeMethod()) {
217             buf.append("(Native Method)");
218         } else {
219             String fName = getFileName();
220 
221             if (fName == null) {
222                 buf.append("(Unknown Source)");
223             } else {
224                 int lineNum = getLineNumber();
225 
226                 buf.append('(');
227                 buf.append(fName);
228                 if (lineNum >= 0) {
229                     buf.append(':');
230                     buf.append(lineNum);
231                 }
232                 buf.append(')');
233             }
234         }
235         return buf.toString();
236     }
237 }
238