Home | History | Annotate | Download | only in lang
      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     private static final int NATIVE_LINE_NUMBER = -2;
     34 
     35     String declaringClass;
     36 
     37     String methodName;
     38 
     39     String fileName;
     40 
     41     int lineNumber;
     42 
     43     /**
     44      * Constructs a new {@code StackTraceElement} for a specified execution
     45      * point.
     46      *
     47      * @param cls
     48      *            the fully qualified name of the class where execution is at.
     49      * @param method
     50      *            the name of the method where execution is at.
     51      * @param file
     52      *            The name of the file where execution is at or {@code null}.
     53      * @param line
     54      *            the line of the file where execution is at, a negative number
     55      *            if unknown or {@code -2} if the execution is in a native
     56      *            method.
     57      * @throws NullPointerException
     58      *             if {@code cls} or {@code method} is {@code null}.
     59      */
     60     public StackTraceElement(String cls, String method, String file, int line) {
     61         if (cls == null) {
     62             throw new NullPointerException("cls == null");
     63         } else if (method == null) {
     64             throw new NullPointerException("method == null");
     65         }
     66         declaringClass = cls;
     67         methodName = method;
     68         fileName = file;
     69         lineNumber = line;
     70     }
     71 
     72     /**
     73      * <p>
     74      * Private, nullary constructor for VM use only.
     75      * </p>
     76      */
     77     private StackTraceElement() {
     78     }
     79 
     80     /**
     81      * Compares this instance with the specified object and indicates if they
     82      * are equal. In order to be equal, the following conditions must be
     83      * fulfilled:
     84      * <ul>
     85      * <li>{@code obj} must be a stack trace element,</li>
     86      * <li>the method names of this stack trace element and of {@code obj} must
     87      * not be {@code null},</li>
     88      * <li>the class, method and file names as well as the line number of this
     89      * stack trace element and of {@code obj} must be equal.</li>
     90      * </ul>
     91      *
     92      * @param obj
     93      *            the object to compare this instance with.
     94      * @return {@code true} if the specified object is equal to this
     95      *         {@code StackTraceElement}; {@code false} otherwise.
     96      * @see #hashCode
     97      */
     98     @Override
     99     public boolean equals(Object obj) {
    100         if (!(obj instanceof StackTraceElement)) {
    101             return false;
    102         }
    103         StackTraceElement castObj = (StackTraceElement) obj;
    104 
    105         /*
    106          * Unknown methods are never equal to anything (not strictly to spec,
    107          * but spec does not allow null method/class names)
    108          */
    109         if ((methodName == null) || (castObj.methodName == null)) {
    110             return false;
    111         }
    112 
    113         if (!getMethodName().equals(castObj.getMethodName())) {
    114             return false;
    115         }
    116         if (!getClassName().equals(castObj.getClassName())) {
    117             return false;
    118         }
    119         String localFileName = getFileName();
    120         if (localFileName == null) {
    121             if (castObj.getFileName() != null) {
    122                 return false;
    123             }
    124         } else {
    125             if (!localFileName.equals(castObj.getFileName())) {
    126                 return false;
    127             }
    128         }
    129         if (getLineNumber() != castObj.getLineNumber()) {
    130             return false;
    131         }
    132 
    133         return true;
    134     }
    135 
    136     /**
    137      * Returns the fully qualified name of the class belonging to this
    138      * {@code StackTraceElement}.
    139      *
    140      * @return the fully qualified type name of the class
    141      */
    142     public String getClassName() {
    143         return (declaringClass == null) ? "<unknown class>" : declaringClass;
    144     }
    145 
    146     /**
    147      * Returns the name of the Java source file containing class belonging to
    148      * this {@code StackTraceElement}.
    149      *
    150      * @return the name of the file, or {@code null} if this information is not
    151      *         available.
    152      */
    153     public String getFileName() {
    154         return fileName;
    155     }
    156 
    157     /**
    158      * Returns the line number in the source for the class belonging to this
    159      * {@code StackTraceElement}.
    160      *
    161      * @return the line number, or a negative number if this information is not
    162      *         available.
    163      */
    164     public int getLineNumber() {
    165         return lineNumber;
    166     }
    167 
    168     /**
    169      * Returns the name of the method belonging to this {@code
    170      * StackTraceElement}.
    171      *
    172      * @return the name of the method, or "<unknown method>" if this information
    173      *         is not available.
    174      */
    175     public String getMethodName() {
    176         return (methodName == null) ? "<unknown method>" : methodName;
    177     }
    178 
    179     @Override
    180     public int hashCode() {
    181         /*
    182          * Either both methodName and declaringClass are null, or neither are
    183          * null.
    184          */
    185         if (methodName == null) {
    186             // all unknown methods hash the same
    187             return 0;
    188         }
    189         // declaringClass never null if methodName is non-null
    190         return methodName.hashCode() ^ declaringClass.hashCode();
    191     }
    192 
    193     /**
    194      * Indicates if the method name returned by {@link #getMethodName()} is
    195      * implemented as a native method.
    196      *
    197      * @return {@code true} if the method in which this stack trace element is
    198      *         executing is a native method; {@code false} otherwise.
    199      */
    200     public boolean isNativeMethod() {
    201         return lineNumber == NATIVE_LINE_NUMBER;
    202     }
    203 
    204     @Override
    205     public String toString() {
    206         StringBuilder buf = new StringBuilder(80);
    207 
    208         buf.append(getClassName());
    209         buf.append('.');
    210         buf.append(getMethodName());
    211 
    212         if (isNativeMethod()) {
    213             buf.append("(Native Method)");
    214         } else {
    215             String fName = getFileName();
    216 
    217             if (fName == null) {
    218                 buf.append("(Unknown Source)");
    219             } else {
    220                 int lineNum = getLineNumber();
    221 
    222                 buf.append('(');
    223                 buf.append(fName);
    224                 if (lineNum >= 0) {
    225                     buf.append(':');
    226                     buf.append(lineNum);
    227                 }
    228                 buf.append(')');
    229             }
    230         }
    231         return buf.toString();
    232     }
    233 }
    234