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