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