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