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 
26 package java.lang;
27 
28 import jdk.internal.loader.BuiltinClassLoader;
29 import jdk.internal.misc.VM;
30 import jdk.internal.module.ModuleHashes;
31 import jdk.internal.module.ModuleReferenceImpl;
32 
33 import java.lang.module.ModuleDescriptor.Version;
34 import java.lang.module.ModuleReference;
35 import java.lang.module.ResolvedModule;
36 import java.util.HashSet;
37 import java.util.Objects;
38 import java.util.Optional;
39 import java.util.Set;
40 
41 /**
42  * An element in a stack trace, as returned by {@link
43  * Throwable#getStackTrace()}.  Each element represents a single stack frame.
44  * All stack frames except for the one at the top of the stack represent
45  * a method invocation.  The frame at the top of the stack represents the
46  * execution point at which the stack trace was generated.  Typically,
47  * this is the point at which the throwable corresponding to the stack trace
48  * was created.
49  *
50  * @since  1.4
51  * @author Josh Bloch
52  */
53 public final class StackTraceElement implements java.io.Serializable {
54 
55     // For Throwables and StackWalker, the VM initially sets this field to a
56     // reference to the declaring Class.  The Class reference is used to
57     // construct the 'format' bitmap, and then is cleared.
58     //
59     // For STEs constructed using the public constructors, this field is not used.
60     private transient Class<?> declaringClassObject;
61 
62     // Normally initialized by VM
63     private String classLoaderName;
64     private String moduleName;
65     private String moduleVersion;
66     private String declaringClass;
67     private String methodName;
68     private String fileName;
69     private int    lineNumber;
70     private byte   format = 0; // Default to show all
71 
72     /**
73      * Creates a stack trace element representing the specified execution
74      * point. The {@link #getModuleName module name} and {@link
75      * #getModuleVersion module version} of the stack trace element will
76      * be {@code null}.
77      *
78      * @param declaringClass the fully qualified name of the class containing
79      *        the execution point represented by the stack trace element
80      * @param methodName the name of the method containing the execution point
81      *        represented by the stack trace element
82      * @param fileName the name of the file containing the execution point
83      *         represented by the stack trace element, or {@code null} if
84      *         this information is unavailable
85      * @param lineNumber the line number of the source line containing the
86      *         execution point represented by this stack trace element, or
87      *         a negative number if this information is unavailable. A value
88      *         of -2 indicates that the method containing the execution point
89      *         is a native method
90      * @throws NullPointerException if {@code declaringClass} or
91      *         {@code methodName} is null
92      * @since 1.5
93      * @revised 9
94      * @spec JPMS
95      */
StackTraceElement(String declaringClass, String methodName, String fileName, int lineNumber)96     public StackTraceElement(String declaringClass, String methodName,
97                              String fileName, int lineNumber) {
98         this(null, null, null, declaringClass, methodName, fileName, lineNumber);
99     }
100 
101     /**
102      * Creates a stack trace element representing the specified execution
103      * point.
104      *
105      * @param classLoaderName the class loader name if the class loader of
106      *        the class containing the execution point represented by
107      *        the stack trace is named; otherwise {@code null}
108      * @param moduleName the module name if the class containing the
109      *        execution point represented by the stack trace is in a named
110      *        module; otherwise {@code null}
111      * @param moduleVersion the module version if the class containing the
112      *        execution point represented by the stack trace is in a named
113      *        module that has a version; otherwise {@code null}
114      * @param declaringClass the fully qualified name of the class containing
115      *        the execution point represented by the stack trace element
116      * @param methodName the name of the method containing the execution point
117      *        represented by the stack trace element
118      * @param fileName the name of the file containing the execution point
119      *        represented by the stack trace element, or {@code null} if
120      *        this information is unavailable
121      * @param lineNumber the line number of the source line containing the
122      *        execution point represented by this stack trace element, or
123      *        a negative number if this information is unavailable. A value
124      *        of -2 indicates that the method containing the execution point
125      *        is a native method
126      *
127      * @throws NullPointerException if {@code declaringClass} is {@code null}
128      *         or {@code methodName} is {@code null}
129      *
130      * @since 9
131      * @spec JPMS
132      */
StackTraceElement(String classLoaderName, String moduleName, String moduleVersion, String declaringClass, String methodName, String fileName, int lineNumber)133     public StackTraceElement(String classLoaderName,
134                              String moduleName, String moduleVersion,
135                              String declaringClass, String methodName,
136                              String fileName, int lineNumber) {
137         this.classLoaderName = classLoaderName;
138         this.moduleName      = moduleName;
139         this.moduleVersion   = moduleVersion;
140         this.declaringClass  = Objects.requireNonNull(declaringClass, "Declaring class is null");
141         this.methodName      = Objects.requireNonNull(methodName, "Method name is null");
142         this.fileName        = fileName;
143         this.lineNumber      = lineNumber;
144     }
145 
146     /*
147      * Private constructor for the factory methods to create StackTraceElement
148      * for Throwable and StackFrameInfo
149      */
StackTraceElement()150     private StackTraceElement() {}
151 
152     /**
153      * Returns the name of the source file containing the execution point
154      * represented by this stack trace element.  Generally, this corresponds
155      * to the {@code SourceFile} attribute of the relevant {@code class}
156      * file (as per <i>The Java Virtual Machine Specification</i>, Section
157      * 4.7.7).  In some systems, the name may refer to some source code unit
158      * other than a file, such as an entry in source repository.
159      *
160      * @return the name of the file containing the execution point
161      *         represented by this stack trace element, or {@code null} if
162      *         this information is unavailable.
163      */
getFileName()164     public String getFileName() {
165         return fileName;
166     }
167 
168     /**
169      * Returns the line number of the source line containing the execution
170      * point represented by this stack trace element.  Generally, this is
171      * derived from the {@code LineNumberTable} attribute of the relevant
172      * {@code class} file (as per <i>The Java Virtual Machine
173      * Specification</i>, Section 4.7.8).
174      *
175      * @return the line number of the source line containing the execution
176      *         point represented by this stack trace element, or a negative
177      *         number if this information is unavailable.
178      */
getLineNumber()179     public int getLineNumber() {
180         return lineNumber;
181     }
182 
183     /**
184      * Returns the module name of the module containing the execution point
185      * represented by this stack trace element.
186      *
187      * @return the module name of the {@code Module} containing the execution
188      *         point represented by this stack trace element; {@code null}
189      *         if the module name is not available.
190      * @since 9
191      * @spec JPMS
192      * @see Module#getName()
193      */
getModuleName()194     public String getModuleName() {
195         return moduleName;
196     }
197 
198     /**
199      * Returns the module version of the module containing the execution point
200      * represented by this stack trace element.
201      *
202      * @return the module version of the {@code Module} containing the execution
203      *         point represented by this stack trace element; {@code null}
204      *         if the module version is not available.
205      * @since 9
206      * @spec JPMS
207      * @see java.lang.module.ModuleDescriptor.Version
208      */
getModuleVersion()209     public String getModuleVersion() {
210         return moduleVersion;
211     }
212 
213     /**
214      * Returns the name of the class loader of the class containing the
215      * execution point represented by this stack trace element.
216      *
217      * @return the name of the class loader of the class containing the execution
218      *         point represented by this stack trace element; {@code null}
219      *         if the class loader is not named.
220      *
221      * @since 9
222      * @spec JPMS
223      * @see java.lang.ClassLoader#getName()
224      */
getClassLoaderName()225     public String getClassLoaderName() {
226         return classLoaderName;
227     }
228 
229     /**
230      * Returns the fully qualified name of the class containing the
231      * execution point represented by this stack trace element.
232      *
233      * @return the fully qualified name of the {@code Class} containing
234      *         the execution point represented by this stack trace element.
235      */
getClassName()236     public String getClassName() {
237         return declaringClass;
238     }
239 
240     /**
241      * Returns the name of the method containing the execution point
242      * represented by this stack trace element.  If the execution point is
243      * contained in an instance or class initializer, this method will return
244      * the appropriate <i>special method name</i>, {@code <init>} or
245      * {@code <clinit>}, as per Section 3.9 of <i>The Java Virtual
246      * Machine Specification</i>.
247      *
248      * @return the name of the method containing the execution point
249      *         represented by this stack trace element.
250      */
getMethodName()251     public String getMethodName() {
252         return methodName;
253     }
254 
255     /**
256      * Returns true if the method containing the execution point
257      * represented by this stack trace element is a native method.
258      *
259      * @return {@code true} if the method containing the execution point
260      *         represented by this stack trace element is a native method.
261      */
isNativeMethod()262     public boolean isNativeMethod() {
263         return lineNumber == -2;
264     }
265 
266     /**
267      * Returns a string representation of this stack trace element.
268      *
269      * @apiNote The format of this string depends on the implementation, but the
270      * following examples may be regarded as typical:
271      * <ul>
272      * <li>
273      *     "{@code com.foo.loader/foo@9.0/com.foo.Main.run(Main.java:101)}"
274      * - See the description below.
275      * </li>
276      * <li>
277      *     "{@code com.foo.loader/foo@9.0/com.foo.Main.run(Main.java)}"
278      * - The line number is unavailable.
279      * </li>
280      * <li>
281      *     "{@code com.foo.loader/foo@9.0/com.foo.Main.run(Unknown Source)}"
282      * - Neither the file name nor the line number is available.
283      * </li>
284      * <li>
285      *     "{@code com.foo.loader/foo@9.0/com.foo.Main.run(Native Method)}"
286      * - The method containing the execution point is a native method.
287      * </li>
288      * <li>
289      *     "{@code com.foo.loader//com.foo.bar.App.run(App.java:12)}"
290      * - The class of the execution point is defined in the unnamed module of
291      * the class loader named {@code com.foo.loader}.
292      * </li>
293      * <li>
294      *     "{@code acme@2.1/org.acme.Lib.test(Lib.java:80)}"
295      * - The class of the execution point is defined in {@code acme} module
296      * loaded by a built-in class loader such as the application class loader.
297      * </li>
298      * <li>
299      *     "{@code MyClass.mash(MyClass.java:9)}"
300      * - {@code MyClass} class is on the application class path.
301      * </li>
302      * </ul>
303      *
304      * <p> The first example shows a stack trace element consisting of
305      * three elements, each separated by {@code "/"} followed with
306      * the source file name and the line number of the source line
307      * containing the execution point.
308      *
309      * The first element "{@code com.foo.loader}" is
310      * the name of the class loader.  The second element "{@code foo@9.0}"
311      * is the module name and version.  The third element is the method
312      * containing the execution point; "{@code com.foo.Main"}" is the
313      * fully-qualified class name and "{@code run}" is the name of the method.
314      * "{@code Main.java}" is the source file name and "{@code 101}" is
315      * the line number.
316      *
317      * <p> If a class is defined in an <em>unnamed module</em>
318      * then the second element is omitted as shown in
319      * "{@code com.foo.loader//com.foo.bar.App.run(App.java:12)}".
320      *
321      * <p> If the class loader is a <a href="ClassLoader.html#builtinLoaders">
322      * built-in class loader</a> or is not named then the first element
323      * and its following {@code "/"} are omitted as shown in
324      * "{@code acme@2.1/org.acme.Lib.test(Lib.java:80)}".
325      * If the first element is omitted and the module is an unnamed module,
326      * the second element and its following {@code "/"} are also omitted
327      * as shown in "{@code MyClass.mash(MyClass.java:9)}".
328      *
329      * <p> The {@code toString} method may return two different values on two
330      * {@code StackTraceElement} instances that are
331      * {@linkplain #equals(Object) equal}, for example one created via the
332      * constructor, and one obtained from {@link java.lang.Throwable} or
333      * {@link java.lang.StackWalker.StackFrame}, where an implementation may
334      * choose to omit some element in the returned string.
335      *
336      * @revised 9
337      * @spec JPMS
338      * @see    Throwable#printStackTrace()
339      */
toString()340     public String toString() {
341         String s = "";
342         if (!dropClassLoaderName() && classLoaderName != null &&
343                 !classLoaderName.isEmpty()) {
344             s += classLoaderName + "/";
345         }
346         if (moduleName != null && !moduleName.isEmpty()) {
347             s += moduleName;
348 
349             if (!dropModuleVersion() && moduleVersion != null &&
350                     !moduleVersion.isEmpty()) {
351                 s += "@" + moduleVersion;
352             }
353         }
354         s = s.isEmpty() ? declaringClass : s + "/" + declaringClass;
355 
356         return s + "." + methodName + "(" +
357              (isNativeMethod() ? "Native Method)" :
358               (fileName != null && lineNumber >= 0 ?
359                fileName + ":" + lineNumber + ")" :
360                 (fileName != null ?  ""+fileName+")" : "Unknown Source)")));
361     }
362 
363     /**
364      * Returns true if the specified object is another
365      * {@code StackTraceElement} instance representing the same execution
366      * point as this instance.  Two stack trace elements {@code a} and
367      * {@code b} are equal if and only if:
368      * <pre>{@code
369      *     equals(a.getClassLoaderName(), b.getClassLoaderName()) &&
370      *     equals(a.getModuleName(), b.getModuleName()) &&
371      *     equals(a.getModuleVersion(), b.getModuleVersion()) &&
372      *     equals(a.getClassName(), b.getClassName()) &&
373      *     equals(a.getMethodName(), b.getMethodName())
374      *     equals(a.getFileName(), b.getFileName()) &&
375      *     a.getLineNumber() == b.getLineNumber()
376      *
377      * }</pre>
378      * where {@code equals} has the semantics of {@link
379      * java.util.Objects#equals(Object, Object) Objects.equals}.
380      *
381      * @param  obj the object to be compared with this stack trace element.
382      * @return true if the specified object is another
383      *         {@code StackTraceElement} instance representing the same
384      *         execution point as this instance.
385      *
386      * @revised 9
387      * @spec JPMS
388      */
equals(Object obj)389     public boolean equals(Object obj) {
390         if (obj==this)
391             return true;
392         if (!(obj instanceof StackTraceElement))
393             return false;
394         StackTraceElement e = (StackTraceElement)obj;
395         return Objects.equals(classLoaderName, e.classLoaderName) &&
396             Objects.equals(moduleName, e.moduleName) &&
397             Objects.equals(moduleVersion, e.moduleVersion) &&
398             e.declaringClass.equals(declaringClass) &&
399             e.lineNumber == lineNumber &&
400             Objects.equals(methodName, e.methodName) &&
401             Objects.equals(fileName, e.fileName);
402     }
403 
404     /**
405      * Returns a hash code value for this stack trace element.
406      */
hashCode()407     public int hashCode() {
408         int result = 31*declaringClass.hashCode() + methodName.hashCode();
409         result = 31*result + Objects.hashCode(classLoaderName);
410         result = 31*result + Objects.hashCode(moduleName);
411         result = 31*result + Objects.hashCode(moduleVersion);
412         result = 31*result + Objects.hashCode(fileName);
413         result = 31*result + lineNumber;
414         return result;
415     }
416 
417 
418     /**
419      * Called from of() methods to set the 'format' bitmap using the Class
420      * reference stored in declaringClassObject, and then clear the reference.
421      *
422      * <p>
423      * If the module is a non-upgradeable JDK module, then set
424      * JDK_NON_UPGRADEABLE_MODULE to omit its version string.
425      * <p>
426      * If the loader is one of the built-in loaders (`boot`, `platform`, or `app`)
427      * then set BUILTIN_CLASS_LOADER to omit the first element (`<loader>/`).
428      */
computeFormat()429     private synchronized void computeFormat() {
430         try {
431             Class<?> cls = (Class<?>) declaringClassObject;
432             ClassLoader loader = cls.getClassLoader0();
433             Module m = cls.getModule();
434             byte bits = 0;
435 
436             // First element - class loader name
437             // Call package-private ClassLoader::name method
438 
439             if (loader instanceof BuiltinClassLoader) {
440                 bits |= BUILTIN_CLASS_LOADER;
441             }
442 
443             // Second element - module name and version
444 
445             // Omit if is a JDK non-upgradeable module (recorded in the hashes
446             // in java.base)
447             if (isHashedInJavaBase(m)) {
448                 bits |= JDK_NON_UPGRADEABLE_MODULE;
449             }
450             format = bits;
451         } finally {
452             // Class reference no longer needed, clear it
453             declaringClassObject = null;
454         }
455     }
456 
457     private static final byte BUILTIN_CLASS_LOADER       = 0x1;
458     private static final byte JDK_NON_UPGRADEABLE_MODULE = 0x2;
459 
dropClassLoaderName()460     private boolean dropClassLoaderName() {
461         return (format & BUILTIN_CLASS_LOADER) == BUILTIN_CLASS_LOADER;
462     }
463 
dropModuleVersion()464     private boolean dropModuleVersion() {
465         return (format & JDK_NON_UPGRADEABLE_MODULE) == JDK_NON_UPGRADEABLE_MODULE;
466     }
467 
468     /**
469      * Returns true if the module is hashed with java.base.
470      * <p>
471      * This method returns false when running on the exploded image
472      * since JDK modules are not hashed. They have no Version attribute
473      * and so "@<version>" part will be omitted anyway.
474      */
isHashedInJavaBase(Module m)475     private static boolean isHashedInJavaBase(Module m) {
476         // return true if module system is not initialized as the code
477         // must be in java.base
478         if (!VM.isModuleSystemInited())
479             return true;
480 
481         return ModuleLayer.boot() == m.getLayer() && HashedModules.contains(m);
482     }
483 
484     /*
485      * Finds JDK non-upgradeable modules, i.e. the modules that are
486      * included in the hashes in java.base.
487      */
488     private static class HashedModules {
489         static Set<String> HASHED_MODULES = hashedModules();
490 
hashedModules()491         static Set<String> hashedModules() {
492 
493             Optional<ResolvedModule> resolvedModule = ModuleLayer.boot()
494                     .configuration()
495                     .findModule("java.base");
496             assert resolvedModule.isPresent();
497             ModuleReference mref = resolvedModule.get().reference();
498             assert mref instanceof ModuleReferenceImpl;
499             ModuleHashes hashes = ((ModuleReferenceImpl)mref).recordedHashes();
500             if (hashes != null) {
501                 Set<String> names = new HashSet<>(hashes.names());
502                 names.add("java.base");
503                 return names;
504             }
505 
506             return Set.of();
507         }
508 
contains(Module m)509         static boolean contains(Module m) {
510             return HASHED_MODULES.contains(m.getName());
511         }
512     }
513 
514 
515     /*
516      * Returns an array of StackTraceElements of the given depth
517      * filled from the backtrace of a given Throwable.
518      */
of(Throwable x, int depth)519     static StackTraceElement[] of(Throwable x, int depth) {
520         StackTraceElement[] stackTrace = new StackTraceElement[depth];
521         for (int i = 0; i < depth; i++) {
522             stackTrace[i] = new StackTraceElement();
523         }
524 
525         // VM to fill in StackTraceElement
526         initStackTraceElements(stackTrace, x);
527 
528         // ensure the proper StackTraceElement initialization
529         for (StackTraceElement ste : stackTrace) {
530             ste.computeFormat();
531         }
532         return stackTrace;
533     }
534 
535     /*
536      * Returns a StackTraceElement from a given StackFrameInfo.
537      */
of(StackFrameInfo sfi)538     static StackTraceElement of(StackFrameInfo sfi) {
539         StackTraceElement ste = new StackTraceElement();
540         initStackTraceElement(ste, sfi);
541 
542         ste.computeFormat();
543         return ste;
544     }
545 
546     /*
547      * Sets the given stack trace elements with the backtrace
548      * of the given Throwable.
549      */
initStackTraceElements(StackTraceElement[] elements, Throwable x)550     private static native void initStackTraceElements(StackTraceElement[] elements,
551                                                       Throwable x);
552     /*
553      * Sets the given stack trace element with the given StackFrameInfo
554      */
initStackTraceElement(StackTraceElement element, StackFrameInfo sfi)555     private static native void initStackTraceElement(StackTraceElement element,
556                                                      StackFrameInfo sfi);
557 
558     private static final long serialVersionUID = 6992337162326171013L;
559 }
560