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