--- old/hotspot/src/share/vm/classfile/javaClasses.cpp 2016-12-07 11:06:51.918708401 -0800 +++ new/hotspot/src/share/vm/classfile/javaClasses.cpp 2016-12-07 11:06:51.822708405 -0800 @@ -3650,7 +3650,7 @@ int java_lang_StackTraceElement::moduleVersion_offset; int java_lang_StackTraceElement::classLoaderName_offset; int java_lang_StackTraceElement::declaringClass_offset; -int java_lang_StackTraceElement::classOrLoaderModuleClassName_offset; +int java_lang_StackTraceElement::declaringClassObj_offset; int java_lang_StackFrameInfo::_declaringClass_offset; int java_lang_StackFrameInfo::_memberName_offset; int java_lang_StackFrameInfo::_bci_offset; @@ -3700,7 +3700,7 @@ } void java_lang_StackTraceElement::set_declaringClassObject(oop element, oop value) { - element->obj_field_put(classOrLoaderModuleClassName_offset, value); + element->obj_field_put(declaringClassObj_offset, value); } // Support for java_lang_StackFrameInfo @@ -3818,7 +3818,7 @@ java_lang_System::static_security_offset = java_lang_System::hc_static_security_offset * x; // java_lang_StackTraceElement - java_lang_StackTraceElement::classOrLoaderModuleClassName_offset= java_lang_StackTraceElement::hc_classOrLoaderModuleClassName_offset* x + header; + java_lang_StackTraceElement::declaringClassObj_offset = java_lang_StackTraceElement::hc_declaringClassObj_offset * x + header; java_lang_StackTraceElement::classLoaderName_offset = java_lang_StackTraceElement::hc_classLoaderName_offset * x + header; java_lang_StackTraceElement::moduleName_offset = java_lang_StackTraceElement::hc_moduleName_offset * x + header; java_lang_StackTraceElement::moduleVersion_offset = java_lang_StackTraceElement::hc_moduleVersion_offset * x + header; --- old/hotspot/src/share/vm/classfile/javaClasses.hpp 2016-12-07 11:06:52.298708387 -0800 +++ new/hotspot/src/share/vm/classfile/javaClasses.hpp 2016-12-07 11:06:52.214708390 -0800 @@ -1297,7 +1297,7 @@ class java_lang_StackTraceElement: AllStatic { private: enum { - hc_classOrLoaderModuleClassName_offset = 0, + hc_declaringClassObj_offset = 0, hc_classLoaderName_offset = 1, hc_moduleName_offset = 2, hc_moduleVersion_offset = 3, @@ -1307,7 +1307,7 @@ hc_lineNumber_offset = 7 }; - static int classOrLoaderModuleClassName_offset; + static int declaringClassObj_offset; static int classLoaderName_offset; static int moduleName_offset; static int moduleVersion_offset; --- 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 `