--- old/jdk/src/java.base/share/classes/java/lang/StackTraceElement.java 2016-12-07 11:06:52.778708369 -0800 +++ new/jdk/src/java.base/share/classes/java/lang/StackTraceElement.java 2016-12-07 11:06:52.582708376 -0800 @@ -30,7 +30,6 @@ import jdk.internal.misc.VM; import jdk.internal.module.ModuleHashes; -import java.lang.module.ModuleDescriptor.Version; import java.lang.reflect.Layer; import java.lang.reflect.Module; import java.util.HashSet; @@ -51,12 +50,13 @@ * @author Josh Bloch */ public final class StackTraceElement implements java.io.Serializable { - // This field is set to the compacted String representation used - // by StackTraceElement::toString and stored in serial form. + + // For Throwables and StackWalker, the VM initially sets this field to a + // reference to the declaring Class. The Class reference is used to + // construct the 'format' bitmap, and then is cleared. // - // This field is of Object type. VM initially sets this field to - // the Class object of the declaring class to build the compacted string. - private Object classOrLoaderModuleClassName; + // For STEs constructed using the public constructors, this field is not used. + private transient Class> declaringClassObject; // Normally initialized by VM private String classLoaderName; @@ -66,6 +66,7 @@ private String methodName; private String fileName; private int lineNumber; + private byte format = 0; // Default to show all /** * Creates a stack trace element representing the specified execution @@ -256,9 +257,10 @@ } /** - * Returns a string representation of this stack trace element. The - * format of this string depends on the implementation, but the following - * examples may be regarded as typical: + * Returns a string representation of this stack trace element. + * + * @apiNote The format of this string depends on the implementation, but the + * following examples may be regarded as typical: *
If the class loader is a * built-in class loader or is not named then the first element * and its following {@code "/"} are omitted as shown in * "{@code acme@2.1/org.acme.Lib.test(Lib.java:80)}". @@ -317,25 +319,28 @@ * the second element and its following {@code "/"} are also omitted * as shown in "{@code MyClass.mash(MyClass.java:9)}". * + *
Note that different values can be returned from {@link toString()} for
+ * StackTraceElements that are otherwise {@linkplain #equals(Object) equal}.
+ * For instance, the class loader name is omitted for built-in class loaders,
+ * but not for other class loaders.
+ *
* @see Throwable#printStackTrace()
*/
public String toString() {
- String s = buildLoaderModuleClassName();
- if (s == null) {
- // all elements will be included
- s = "";
- if (classLoaderName != null && !classLoaderName.isEmpty()) {
- s += classLoaderName + "/";
- }
- if (moduleName != null && !moduleName.isEmpty()) {
- s += moduleName;
+ String s = "";
+ if (!has(BUILTIN_CLASS_LOADER) && classLoaderName != null &&
+ !classLoaderName.isEmpty()) {
+ s += classLoaderName + "/";
+ }
+ if (moduleName != null && !moduleName.isEmpty()) {
+ s += moduleName;
- if (moduleVersion != null && !moduleVersion.isEmpty()) {
- s += "@" + moduleVersion;
- }
+ if (!has(JDK_NON_UPGRADEABLE_MODULE) && moduleVersion != null &&
+ !moduleVersion.isEmpty()) {
+ s += "@" + moduleVersion;
}
- s = s.isEmpty() ? declaringClass : s + "/" + declaringClass;
}
+ s = s.isEmpty() ? declaringClass : s + "/" + declaringClass;
return s + "." + methodName + "(" +
(isNativeMethod() ? "Native Method)" :
@@ -362,6 +367,10 @@
* where {@code equals} has the semantics of {@link
* java.util.Objects#equals(Object, Object) Objects.equals}.
*
+ * @apiNote StackTraceElements can be equal, but return different
+ * {@link toString()} values, due to the specifics of how the
+ * {@link toString()} return value is constructed.
+ *
* @param obj the object to be compared with this stack trace element.
* @return true if the specified object is another
* {@code StackTraceElement} instance representing the same
@@ -397,67 +406,43 @@
/**
- * Build the compacted String representation to be returned by
- * toString method from the declaring Class object.
+ * Called from of() methods to set the 'format' bitmap using the Class
+ * reference stored in declaringClassObject, and then clear the reference.
*/
- synchronized String buildLoaderModuleClassName() {
- if (classOrLoaderModuleClassName == null)
- return null;
-
- if (classOrLoaderModuleClassName instanceof Class) {
- Class> cls = (Class>)classOrLoaderModuleClassName;
- classOrLoaderModuleClassName = toLoaderModuleClassName(cls);
- }
- return (String)classOrLoaderModuleClassName;
- }
+ private synchronized void computeFormat() {
+ try {
+ Class> cls = (Class>) declaringClassObject;
+ ClassLoader loader = cls.getClassLoader0();
+ Module m = cls.getModule();
+ byte bits = 0;
- /**
- * Returns
- * If the module is a non-upgradeable JDK module then omit
- * its version string.
- *
- * If the loader has no name, or if the loader is one of the built-in
- * loaders (`boot`, `platform`, or `app`) then drop the first element
- * (`
- * If the first element has been dropped and the module is unnamed
- * then drop the second element (`
- * If the first element is not dropped and the module is unnamed
- * then drop `